Bug 1397831 - Update webrender to commit 6cf9cd4075efdf7467bad71b372170f626a8fce4. r=jrmuizel

MozReview-Commit-ID: 8SHrjpb5bKs

--HG--
extra : rebase_source : 4718328943014ef62e7cccc566e0fce4c8199073
This commit is contained in:
Ryan Hunt 2017-09-08 11:53:34 -05:00
Родитель ae53820108
Коммит f45c53ec90
18 изменённых файлов: 379 добавлений и 219 удалений

Просмотреть файл

@ -79,4 +79,4 @@ to make sure that mozjs_sys also has its Cargo.lock file updated if needed, henc
the need to run the cargo update command in js/src as well. Hopefully this will
be resolved soon.
Latest Commit: dbffdc219fa394ab1225cebc71fe5998b9337cb2
Latest Commit: 6cf9cd4075efdf7467bad71b372170f626a8fce4

Просмотреть файл

@ -228,7 +228,7 @@ impl FrameBuilder {
clip_and_scroll: ClipAndScrollInfo,
local_clip: &LocalClip,
corner_instances: [BorderCornerInstance; 4],
extra_clips: &[ClipSource]) {
clip_sources: Vec<ClipSource>) {
let radius = &border.radius;
let left = &border.left;
let right = &border.right;
@ -274,7 +274,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&rect,
local_clip,
extra_clips,
clip_sources,
PrimitiveContainer::Border(prim_cpu));
}
@ -425,7 +425,7 @@ impl FrameBuilder {
clip_and_scroll,
local_clip,
corner_instances,
&extra_clips);
extra_clips);
}
}
}

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ComplexClipRegion, ImageMask, ImageRendering};
use api::{BorderRadius, ComplexClipRegion, ImageMask, ImageRendering};
use api::{LayerPoint, LayerRect, LayerToWorldTransform, LocalClip};
use border::BorderCornerClipSource;
use gpu_cache::GpuCache;
@ -49,20 +49,6 @@ impl ClipRegion {
};
ClipRegion::create_for_clip_node(*local_clip.clip_rect(), complex_clips, None)
}
pub fn create_for_local_clip(local_clip: &LocalClip) -> ClipRegion {
let complex_clips = match local_clip {
&LocalClip::Rect(_) => Vec::new(),
&LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
};
ClipRegion {
origin: LayerPoint::zero(),
main: *local_clip.clip_rect(),
image_mask: None,
complex_clips,
}
}
}
#[repr(C)]
@ -83,10 +69,11 @@ impl Not for ClipMode {
}
}
#[derive(Clone, Debug)]
#[derive(Debug)]
pub enum ClipSource {
Complex(LayerRect, f32, ClipMode),
Region(ClipRegion),
Rectangle(LayerRect),
RoundedRectangle(LayerRect, BorderRadius, ClipMode),
Image(ImageMask),
/// TODO(gw): This currently only handles dashed style
/// clips, where the border style is dashed for both
/// adjacent border edges. Expand to handle dotted style
@ -94,6 +81,24 @@ pub enum ClipSource {
BorderCorner(BorderCornerClipSource),
}
impl From<ClipRegion> for ClipSources {
fn from(region: ClipRegion) -> ClipSources {
let mut clips = Vec::new();
if let Some(info) = region.image_mask {
clips.push(ClipSource::Image(info));
}
clips.push(ClipSource::Rectangle(region.main));
for complex in region.complex_clips {
clips.push(ClipSource::RoundedRectangle(complex.rect, complex.radii, ClipMode::Clip));
}
ClipSources::new(clips)
}
}
#[derive(Debug)]
pub struct ClipSources {
clips: Vec<ClipSource>,
@ -130,7 +135,7 @@ impl ClipSources {
device_pixel_ratio);
for clip in &self.clips {
if let ClipSource::Region(ClipRegion{ image_mask: Some(ref mask), .. }, ..) = *clip {
if let ClipSource::Image(ref mask) = *clip {
resource_cache.request_image(mask.image,
ImageRendering::Auto,
None,

Просмотреть файл

@ -6,7 +6,7 @@ use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize};
use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, PipelineId};
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyFrameInfo};
use api::WorldPoint;
use clip::{ClipRegion, ClipSource, ClipSources};
use clip::{ClipRegion, ClipSources};
use clip_scroll_tree::TransformUpdateState;
use geometry::ray_intersects_rect;
use spring::{DAMPING, STIFFNESS, Spring};
@ -42,7 +42,7 @@ impl ClipInfo {
pub fn new(clip_region: ClipRegion, packed_layer_index: PackedLayerIndex) -> ClipInfo {
let clip_rect = LayerRect::new(clip_region.origin, clip_region.main.size);
ClipInfo {
clip_sources: ClipSources::new(vec![ClipSource::Region(clip_region)]),
clip_sources: ClipSources::from(clip_region),
packed_layer_index,
screen_bounding_rect: None,
clip_rect: clip_rect,

Просмотреть файл

@ -4,7 +4,7 @@
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollingState};
use internal_types::{FastHashSet, FastHashMap};
use print_tree::PrintTree;
use print_tree::{PrintTree, PrintTreePrinter};
use api::{ClipId, LayerPoint, LayerRect, LayerToScrollTransform, LayerToWorldTransform};
use api::{LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLayerState};
use api::{ScrollLocation, StickyFrameInfo, WorldPoint};
@ -370,7 +370,7 @@ impl ClipScrollTree {
}
}
fn print_node(&self, id: &ClipId, pt: &mut PrintTree) {
fn print_node<T: PrintTreePrinter>(&self, id: &ClipId, pt: &mut T) {
let node = self.nodes.get(id).unwrap();
match node.node_type {
@ -416,7 +416,13 @@ impl ClipScrollTree {
pub fn print(&self) {
if !self.nodes.is_empty() {
let mut pt = PrintTree::new("clip_scroll tree");
self.print_node(&self.root_reference_frame_id, &mut pt);
self.print_with(&mut pt);
}
}
pub fn print_with<T: PrintTreePrinter>(&self, pt: &mut T) {
if !self.nodes.is_empty() {
self.print_node(&self.root_reference_frame_id, pt);
}
}
}

Просмотреть файл

@ -8,6 +8,7 @@ use std::sync::mpsc::{channel, Receiver};
use std::thread;
use std::sync::mpsc::Sender;
use print_tree::PrintTreePrinter;
use ws;
// Messages that are sent from the render backend to the renderer
@ -65,6 +66,9 @@ impl ws::Handler for Server {
"fetch_documents" => {
DebugCommand::FetchDocuments
}
"fetch_clipscrolltree" => {
DebugCommand::FetchClipScrollTree
}
msg => {
println!("unknown msg {}", msg);
return Ok(());
@ -281,3 +285,66 @@ impl DocumentList {
self.root.add_child(item);
}
}
// A serializable list of debug information about clip-scroll trees
// that can be sent to the client
#[derive(Serialize)]
pub struct ClipScrollTreeList {
kind: &'static str,
root: TreeNode,
}
impl ClipScrollTreeList {
pub fn new() -> ClipScrollTreeList {
ClipScrollTreeList {
kind: "clipscrolltree",
root: TreeNode::new("root"),
}
}
pub fn add(&mut self, item: TreeNode) {
self.root.add_child(item);
}
}
// A TreeNode-based PrintTreePrinter to serialize pretty-printed
// trees as json
pub struct TreeNodeBuilder {
levels: Vec<TreeNode>,
}
impl TreeNodeBuilder {
pub fn new(root: TreeNode) -> TreeNodeBuilder {
TreeNodeBuilder {
levels: vec![root]
}
}
fn current_level_mut(&mut self) -> &mut TreeNode {
assert!(!self.levels.is_empty());
self.levels.last_mut().unwrap()
}
pub fn build(mut self) -> TreeNode {
assert!(self.levels.len() == 1);
self.levels.pop().unwrap()
}
}
impl PrintTreePrinter for TreeNodeBuilder {
fn new_level(&mut self, title: String) {
let level = TreeNode::new(&title);
self.levels.push(level);
}
fn end_level(&mut self) {
assert!(!self.levels.is_empty());
let last_level = self.levels.pop().unwrap();
self.current_level_mut().add_child(last_level);
}
fn add_item(&mut self, text: String) {
self.current_level_mut().add_item(&text);
}
}

Просмотреть файл

@ -398,6 +398,17 @@ impl Texture {
pub fn get_layer_count(&self) -> i32 {
self.layer_count
}
pub fn get_bpp(&self) -> u32 {
match self.format {
ImageFormat::A8 => 1,
ImageFormat::RGB8 => 3,
ImageFormat::BGRA8 => 4,
ImageFormat::RG8 => 2,
ImageFormat::RGBAF32 => 16,
ImageFormat::Invalid => unreachable!(),
}
}
}
impl Drop for Texture {
@ -433,6 +444,16 @@ impl Drop for VAO {
}
}
pub struct PBO {
id: gl::GLuint,
}
impl Drop for PBO {
fn drop(&mut self) {
debug_assert!(thread::panicking() || self.id == 0, "renderer::deinit not called");
}
}
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub struct FBOId(gl::GLuint);
@ -445,9 +466,6 @@ pub struct VBOId(gl::GLuint);
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
struct IBOId(gl::GLuint);
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub struct PBOId(gl::GLuint);
const MAX_TIMERS_PER_FRAME: usize = 256;
const MAX_SAMPLERS_PER_FRAME: usize = 16;
const MAX_PROFILE_FRAMES: usize = 4;
@ -759,7 +777,7 @@ pub struct Device {
bound_textures: [gl::GLuint; 16],
bound_program: gl::GLuint,
bound_vao: gl::GLuint,
bound_pbo: PBOId,
bound_pbo: gl::GLuint,
bound_read_fbo: FBOId,
bound_draw_fbo: FBOId,
default_read_fbo: gl::GLuint,
@ -803,7 +821,7 @@ impl Device {
bound_textures: [0; 16],
bound_program: 0,
bound_vao: 0,
bound_pbo: PBOId(0),
bound_pbo: 0,
bound_read_fbo: FBOId(0),
bound_draw_fbo: FBOId(0),
default_read_fbo: 0,
@ -833,7 +851,7 @@ impl Device {
pub fn reset_state(&mut self) {
self.bound_textures = [0; 16];
self.bound_vao = 0;
self.bound_pbo = PBOId(0);
self.bound_pbo = 0;
self.bound_read_fbo = FBOId(0);
self.bound_draw_fbo = FBOId(0);
}
@ -891,7 +909,7 @@ impl Device {
// Pixel op state
self.gl.pixel_store_i(gl::UNPACK_ALIGNMENT, 1);
self.bound_pbo = PBOId(0);
self.bound_pbo = 0;
self.gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, 0);
// Default is sampler 0, always
@ -1176,7 +1194,7 @@ impl Device {
pub fn free_texture_storage(&mut self, texture: &mut Texture) {
debug_assert!(self.inside_frame);
debug_assert_eq!(self.bound_pbo, PBOId(0));
debug_assert_eq!(self.bound_pbo, 0);
if texture.format == ImageFormat::Invalid {
return;
@ -1352,29 +1370,32 @@ impl Device {
self.gl.uniform_1f(program.u_device_pixel_ratio, self.device_pixel_ratio);
}
pub fn create_pbo(&mut self) -> PBOId {
pub fn create_pbo(&mut self) -> PBO {
let id = self.gl.gen_buffers(1)[0];
PBOId(id)
PBO {
id
}
}
pub fn destroy_pbo(&mut self, id: PBOId) {
self.gl.delete_buffers(&[id.0]);
pub fn delete_pbo(&mut self, mut pbo: PBO) {
self.gl.delete_buffers(&[pbo.id]);
pbo.id = 0;
}
pub fn bind_pbo(&mut self, pbo_id: Option<PBOId>) {
pub fn bind_pbo(&mut self, pbo: Option<&PBO>) {
debug_assert!(self.inside_frame);
let pbo_id = pbo_id.unwrap_or(PBOId(0));
let pbo_id = pbo.map_or(0, |pbo| pbo.id);
if self.bound_pbo != pbo_id {
self.bound_pbo = pbo_id;
self.gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, pbo_id.0);
self.gl.bind_buffer(gl::PIXEL_UNPACK_BUFFER, pbo_id);
}
}
pub fn update_pbo_data<T>(&mut self, data: &[T]) {
debug_assert!(self.inside_frame);
debug_assert_ne!(self.bound_pbo, PBOId(0));
debug_assert_ne!(self.bound_pbo, 0);
gl::buffer_data(&*self.gl,
gl::PIXEL_UNPACK_BUFFER,
@ -1384,7 +1405,7 @@ impl Device {
pub fn orphan_pbo(&mut self, new_size: usize) {
debug_assert!(self.inside_frame);
debug_assert_ne!(self.bound_pbo, PBOId(0));
debug_assert_ne!(self.bound_pbo, 0);
self.gl.buffer_data_untyped(gl::PIXEL_UNPACK_BUFFER,
new_size as isize,

Просмотреть файл

@ -189,6 +189,46 @@ pub struct Frame {
frame_builder: Option<FrameBuilder>,
}
trait FilterOpHelpers {
fn resolve(self, properties: &SceneProperties) -> FilterOp;
fn is_noop(&self) -> bool;
}
impl FilterOpHelpers for FilterOp {
fn resolve(self, properties: &SceneProperties) -> FilterOp {
match self {
FilterOp::Opacity(ref value) => {
let amount = properties.resolve_float(value, 1.0);
FilterOp::Opacity(PropertyBinding::Value(amount))
}
_ => self
}
}
fn is_noop(&self) -> bool {
match *self {
FilterOp::Blur(length) => length == 0.0,
FilterOp::Brightness(amount) => amount == 1.0,
FilterOp::Contrast(amount) => amount == 1.0,
FilterOp::Grayscale(amount) => amount == 0.0,
FilterOp::HueRotate(amount) => amount == 0.0,
FilterOp::Invert(amount) => amount == 0.0,
FilterOp::Opacity(value) => {
match value {
PropertyBinding::Value(amount) => {
amount == 1.0
}
PropertyBinding::Binding(..) => {
panic!("bug: binding value should be resolved");
}
}
}
FilterOp::Saturate(amount) => amount == 1.0,
FilterOp::Sepia(amount) => amount == 0.0,
}
}
}
trait StackingContextHelpers {
fn mix_blend_mode_for_compositing(&self) -> Option<MixBlendMode>;
fn filter_ops_for_compositing(&self,
@ -211,15 +251,11 @@ impl StackingContextHelpers for StackingContext {
properties: &SceneProperties) -> Vec<FilterOp> {
let mut filters = vec![];
for filter in display_list.get(input_filters) {
let filter = filter.resolve(properties);
if filter.is_noop() {
continue;
}
if let FilterOp::Opacity(ref value) = filter {
let amount = properties.resolve_float(value, 1.0);
filters.push(FilterOp::Opacity(PropertyBinding::Value(amount)));
} else {
filters.push(filter);
}
filters.push(filter);
}
filters
}
@ -567,16 +603,22 @@ impl Frame {
info.image_rendering);
}
SpecificDisplayItem::Text(ref text_info) => {
let instance = context.resource_cache.get_font_instance(text_info.font_key).unwrap();
context.builder.add_text(clip_and_scroll,
reference_frame_relative_offset,
item_rect_with_offset,
&clip_with_offset,
instance,
&text_info.color,
item.glyphs(),
item.display_list().get(item.glyphs()).count(),
text_info.glyph_options);
match context.resource_cache.get_font_instance(text_info.font_key) {
Some(instance) => {
context.builder.add_text(clip_and_scroll,
reference_frame_relative_offset,
item_rect_with_offset,
&clip_with_offset,
instance,
&text_info.color,
item.glyphs(),
item.display_list().get(item.glyphs()).count(),
text_info.glyph_options);
}
None => {
warn!("Unknown font instance key: {:?}", text_info.font_key);
}
}
}
SpecificDisplayItem::Rectangle(ref info) => {
if !self.try_to_add_rectangle_splitting_on_clip(context,

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF};
use api::{BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExtendMode, FontInstance, FontRenderMode};
use api::{GlyphInstance, GlyphOptions, GradientStop};
@ -198,13 +198,13 @@ impl FrameBuilder {
clip_and_scroll: ClipAndScrollInfo,
rect: &LayerRect,
local_clip: &LocalClip,
extra_clips: &[ClipSource],
mut clip_sources: Vec<ClipSource>,
container: PrimitiveContainer) -> PrimitiveIndex {
self.create_clip_scroll_group_if_necessary(clip_and_scroll);
let mut clip_sources = extra_clips.to_vec();
if let &LocalClip::RoundedRect(_, _) = local_clip {
clip_sources.push(ClipSource::Region(ClipRegion::create_for_local_clip(local_clip)))
if let &LocalClip::RoundedRect(main, region) = local_clip {
clip_sources.push(ClipSource::Rectangle(main));
clip_sources.push(ClipSource::RoundedRectangle(region.rect, region.radii, ClipMode::Clip));
}
let clip_sources = ClipSources::new(clip_sources);
@ -242,12 +242,12 @@ impl FrameBuilder {
clip_and_scroll: ClipAndScrollInfo,
rect: &LayerRect,
local_clip: &LocalClip,
extra_clips: &[ClipSource],
clip_sources: Vec<ClipSource>,
container: PrimitiveContainer) -> PrimitiveIndex {
let prim_index = self.create_primitive(clip_and_scroll,
rect,
local_clip,
extra_clips,
clip_sources,
container);
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
@ -445,7 +445,7 @@ impl FrameBuilder {
let prim_index = self.add_primitive(clip_and_scroll,
&LayerRect::zero(),
local_clip,
&[],
Vec::new(),
PrimitiveContainer::TextShadow(prim));
self.shadow_prim_stack.push(prim_index);
@ -479,7 +479,7 @@ impl FrameBuilder {
let prim_index = self.add_primitive(clip_and_scroll,
rect,
local_clip,
&[],
Vec::new(),
PrimitiveContainer::Rectangle(prim));
match flags {
@ -535,14 +535,14 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&new_rect.translate(&shadow.offset),
local_clip,
&[],
Vec::new(),
PrimitiveContainer::Line(line));
}
let prim_index = self.create_primitive(clip_and_scroll,
&new_rect,
local_clip,
&[],
Vec::new(),
PrimitiveContainer::Line(line));
if color.a > 0.0 {
@ -830,7 +830,7 @@ impl FrameBuilder {
PrimitiveContainer::AngleGradient(gradient_cpu)
};
self.add_primitive(clip_and_scroll, &rect, local_clip, &[], prim);
self.add_primitive(clip_and_scroll, &rect, local_clip, Vec::new(), prim);
}
pub fn add_radial_gradient(&mut self,
@ -862,7 +862,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&rect,
local_clip,
&[],
Vec::new(),
PrimitiveContainer::RadialGradient(radial_gradient_cpu));
}
@ -974,7 +974,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&rect.translate(&text_prim.offset),
local_clip,
&[],
Vec::new(),
PrimitiveContainer::TextRun(text_prim));
}
@ -983,7 +983,7 @@ impl FrameBuilder {
let prim_index = self.create_primitive(clip_and_scroll,
&rect,
local_clip,
&[],
Vec::new(),
PrimitiveContainer::TextRun(prim));
// Only add a visual element if it can contribute to the scene.
@ -1031,8 +1031,9 @@ impl FrameBuilder {
let box_clip_mode = !bs_clip_mode;
// Clip the inside and then the outside of the box.
let extra_clips = [ClipSource::Complex(bs_rect, border_radius, bs_clip_mode),
ClipSource::Complex(*box_bounds, border_radius, box_clip_mode)];
let border_radius = BorderRadius::uniform(border_radius);
let extra_clips = vec![ClipSource::RoundedRectangle(bs_rect, border_radius, bs_clip_mode),
ClipSource::RoundedRectangle(*box_bounds, border_radius, box_clip_mode)];
let prim = RectanglePrimitive {
color: *color,
@ -1041,7 +1042,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&rect_to_draw,
local_clip,
&extra_clips,
extra_clips,
PrimitiveContainer::Rectangle(prim));
}
@ -1192,9 +1193,9 @@ impl FrameBuilder {
let mut extra_clips = Vec::new();
if border_radius >= 0.0 {
extra_clips.push(ClipSource::Complex(*box_bounds,
border_radius,
extra_clip_mode));
extra_clips.push(ClipSource::RoundedRectangle(*box_bounds,
BorderRadius::uniform(border_radius),
extra_clip_mode));
}
let prim_cpu = BoxShadowPrimitiveCpu {
@ -1211,7 +1212,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&outer_rect,
local_clip,
extra_clips.as_slice(),
extra_clips,
PrimitiveContainer::BoxShadow(prim_cpu));
}
}
@ -1245,7 +1246,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&rect,
local_clip,
&[],
Vec::new(),
PrimitiveContainer::Image(prim_cpu));
}
@ -1276,7 +1277,7 @@ impl FrameBuilder {
self.add_primitive(clip_and_scroll,
&rect,
clip_rect,
&[],
Vec::new(),
PrimitiveContainer::YuvImage(prim_cpu));
}

Просмотреть файл

@ -158,6 +158,7 @@ impl RendererFrame {
pub enum DebugOutput {
FetchDocuments(String),
FetchClipScrollTree(String),
}
pub enum ResultMsg {

Просмотреть файл

@ -2,13 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, LayerPoint, LayerRect};
use api::{DeviceIntRect, ImageMask, LayerPoint, LayerRect};
use api::{LayerSize, LayerToWorldTransform};
use border::BorderCornerClipSource;
use clip::{ClipMode, ClipSource};
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use prim_store::{CLIP_DATA_GPU_BLOCKS, ClipData, ImageMaskData};
use util::{ComplexClipRegionHelpers, TransformedRect};
use util::{extract_inner_rect_safe, TransformedRect};
const MAX_CLIP: f32 = 1000000.0;
@ -114,17 +114,16 @@ impl MaskCacheInfo {
// and if we have an image mask.
for clip in clips {
match *clip {
ClipSource::Complex(..) => {
ClipSource::RoundedRectangle(..) => {
complex_clip_count += 1;
}
ClipSource::Region(ref region) => {
if let Some(info) = region.image_mask {
debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask!
image = Some((info, GpuCacheHandle::new()));
}
complex_clip_count += region.complex_clips.len();
ClipSource::Rectangle(..) => {
layer_clip_count += 1;
}
ClipSource::Image(image_mask) => {
debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask!
image = Some((image_mask, GpuCacheHandle::new()));
}
ClipSource::BorderCorner(ref source) => {
border_corners.push((source.clone(), GpuCacheHandle::new()));
}
@ -149,46 +148,39 @@ impl MaskCacheInfo {
gpu_cache: &mut GpuCache,
device_pixel_ratio: f32)
-> &MaskBounds {
// Step[1] - compute the local bounds
//TODO: move to initialization stage?
if self.bounds.inner.is_none() {
let mut local_rect = Some(LayerRect::new(LayerPoint::new(-MAX_CLIP, -MAX_CLIP),
LayerSize::new(2.0 * MAX_CLIP, 2.0 * MAX_CLIP)));
let mut local_inner: Option<LayerRect> = None;
let mut local_inner = local_rect;
let mut has_clip_out = false;
let has_border_clip = !self.border_corners.is_empty();
for source in sources {
match *source {
ClipSource::Complex(rect, radius, mode) => {
ClipSource::Image(ref mask) => {
if !mask.repeat {
local_rect = local_rect.and_then(|r| r.intersection(&mask.rect));
}
local_inner = None;
}
ClipSource::Rectangle(rect) => {
local_rect = local_rect.and_then(|r| r.intersection(&rect));
local_inner = local_inner.and_then(|r| r.intersection(&rect));
}
ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
has_clip_out = true;
break;
}
local_rect = local_rect.and_then(|r| r.intersection(&rect));
local_inner = ComplexClipRegion::new(rect, BorderRadius::uniform(radius))
.get_inner_rect_safe();
}
ClipSource::Region(ref region) => {
local_rect = local_rect.and_then(|r| r.intersection(&region.main));
local_inner = match region.image_mask {
Some(ref mask) => {
if !mask.repeat {
local_rect = local_rect.and_then(|r| r.intersection(&mask.rect));
}
None
},
None => local_rect,
};
for clip in &region.complex_clips {
local_rect = local_rect.and_then(|r| r.intersection(&clip.rect));
local_inner = local_inner.and_then(|r| clip.get_inner_rect_safe()
.and_then(|ref inner| r.intersection(inner)));
}
local_rect = local_rect.and_then(|r| r.intersection(rect));
let inner_rect = extract_inner_rect_safe(rect, radius);
local_inner = local_inner.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
}
ClipSource::BorderCorner{..} => {}
}
@ -203,13 +195,6 @@ impl MaskCacheInfo {
inner: Some(LayerRect::zero().into()),
}
} else {
// TODO(gw): local inner is only valid if there's a single clip (for now).
// This can be improved in the future, with some proper
// rectangle region handling.
if sources.len() > 1 {
local_inner = None;
}
MaskBounds {
outer: Some(local_rect.unwrap_or(LayerRect::zero()).into()),
inner: Some(local_inner.unwrap_or(LayerRect::zero()).into()),
@ -222,18 +207,9 @@ impl MaskCacheInfo {
if let Some(block_count) = self.complex_clip_range.get_block_count() {
if let Some(mut request) = gpu_cache.request(&mut self.complex_clip_range.location) {
for source in sources {
match *source {
ClipSource::Complex(rect, radius, mode) => {
let data = ClipData::uniform(rect, radius, mode);
data.write(&mut request);
}
ClipSource::Region(ref region) => {
for clip in &region.complex_clips {
let data = ClipData::from_clip_region(&clip);
data.write(&mut request);
}
}
ClipSource::BorderCorner{..} => {}
if let ClipSource::RoundedRectangle(ref rect, ref radius, mode) = *source {
let data = ClipData::rounded_rect(rect, radius, mode);
data.write(&mut request);
}
}
assert_eq!(request.close(), block_count);
@ -243,8 +219,8 @@ impl MaskCacheInfo {
if let Some(block_count) = self.layer_clip_range.get_block_count() {
if let Some(mut request) = gpu_cache.request(&mut self.layer_clip_range.location) {
for source in sources {
if let ClipSource::Region(ref region) = *source {
let data = ClipData::uniform(region.main, 0.0, ClipMode::Clip);
if let ClipSource::Rectangle(rect) = *source {
let data = ClipData::uniform(rect, 0.0, ClipMode::Clip);
data.write(&mut request);
}
}

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect, DeviceIntSize, DevicePoint};
use api::{ExtendMode, FontRenderMode, GlyphInstance, GradientStop};
use api::{BorderRadius, ExtendMode, FontRenderMode, GlyphInstance, GradientStop};
use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize, TextShadow};
use api::{GlyphKey, LayerToWorldTransform, TileOffset, YuvColorSpace, YuvFormat};
use api::{device_length, FontInstance, LayerVector2D, LineOrientation, LineStyle};
@ -651,47 +651,46 @@ pub struct ClipData {
}
impl ClipData {
pub fn from_clip_region(clip: &ComplexClipRegion) -> ClipData {
pub fn rounded_rect(rect: &LayerRect, radii: &BorderRadius, mode: ClipMode) -> ClipData {
ClipData {
rect: ClipRect {
rect: clip.rect,
// TODO(gw): Support other clip modes for regions?
mode: ClipMode::Clip as u32 as f32,
rect: *rect,
mode: mode as u32 as f32,
},
top_left: ClipCorner {
rect: LayerRect::new(
LayerPoint::new(clip.rect.origin.x, clip.rect.origin.y),
LayerSize::new(clip.radii.top_left.width, clip.radii.top_left.height)),
outer_radius_x: clip.radii.top_left.width,
outer_radius_y: clip.radii.top_left.height,
LayerPoint::new(rect.origin.x, rect.origin.y),
LayerSize::new(radii.top_left.width, radii.top_left.height)),
outer_radius_x: radii.top_left.width,
outer_radius_y: radii.top_left.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
top_right: ClipCorner {
rect: LayerRect::new(
LayerPoint::new(clip.rect.origin.x + clip.rect.size.width - clip.radii.top_right.width, clip.rect.origin.y),
LayerSize::new(clip.radii.top_right.width, clip.radii.top_right.height)),
outer_radius_x: clip.radii.top_right.width,
outer_radius_y: clip.radii.top_right.height,
LayerPoint::new(rect.origin.x + rect.size.width - radii.top_right.width, rect.origin.y),
LayerSize::new(radii.top_right.width, radii.top_right.height)),
outer_radius_x: radii.top_right.width,
outer_radius_y: radii.top_right.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
bottom_left: ClipCorner {
rect: LayerRect::new(
LayerPoint::new(clip.rect.origin.x, clip.rect.origin.y + clip.rect.size.height - clip.radii.bottom_left.height),
LayerSize::new(clip.radii.bottom_left.width, clip.radii.bottom_left.height)),
outer_radius_x: clip.radii.bottom_left.width,
outer_radius_y: clip.radii.bottom_left.height,
LayerPoint::new(rect.origin.x, rect.origin.y + rect.size.height - radii.bottom_left.height),
LayerSize::new(radii.bottom_left.width, radii.bottom_left.height)),
outer_radius_x: radii.bottom_left.width,
outer_radius_y: radii.bottom_left.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
bottom_right: ClipCorner {
rect: LayerRect::new(
LayerPoint::new(clip.rect.origin.x + clip.rect.size.width - clip.radii.bottom_right.width,
clip.rect.origin.y + clip.rect.size.height - clip.radii.bottom_right.height),
LayerSize::new(clip.radii.bottom_right.width, clip.radii.bottom_right.height)),
outer_radius_x: clip.radii.bottom_right.width,
outer_radius_y: clip.radii.bottom_right.height,
LayerPoint::new(rect.origin.x + rect.size.width - radii.bottom_right.width,
rect.origin.y + rect.size.height - radii.bottom_right.height),
LayerSize::new(radii.bottom_right.width, radii.bottom_right.height)),
outer_radius_x: radii.bottom_right.width,
outer_radius_y: radii.bottom_right.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},

Просмотреть файл

@ -13,6 +13,15 @@ pub struct PrintTree {
queued_item: Option<String>,
}
/// A trait that makes it easy to describe a pretty tree of data,
/// regardless of the printing destination, to either print it
/// directly to stdout, or serialize it as in the debugger
pub trait PrintTreePrinter {
fn new_level(&mut self, title: String);
fn end_level(&mut self);
fn add_item(&mut self, text: String);
}
impl PrintTree {
pub fn new(title: &str) -> PrintTree {
println!("\u{250c} {}", title);
@ -22,28 +31,6 @@ impl PrintTree {
}
}
/// Descend one level in the tree with the given title.
pub fn new_level(&mut self, title: String) {
self.flush_queued_item("\u{251C}\u{2500}");
self.print_level_prefix();
println!("\u{251C}\u{2500} {}", title);
self.level = self.level + 1;
}
/// Ascend one level in the tree.
pub fn end_level(&mut self) {
self.flush_queued_item("\u{2514}\u{2500}");
self.level = self.level - 1;
}
/// Add an item to the current level in the tree.
pub fn add_item(&mut self, text: String) {
self.flush_queued_item("\u{251C}\u{2500}");
self.queued_item = Some(text);
}
fn print_level_prefix(&self) {
for _ in 0..self.level {
print!("\u{2502} ");
@ -58,6 +45,31 @@ impl PrintTree {
}
}
// The default `println!` based printer
impl PrintTreePrinter for PrintTree {
/// Descend one level in the tree with the given title.
fn new_level(&mut self, title: String) {
self.flush_queued_item("\u{251C}\u{2500}");
self.print_level_prefix();
println!("\u{251C}\u{2500} {}", title);
self.level = self.level + 1;
}
/// Ascend one level in the tree.
fn end_level(&mut self) {
self.flush_queued_item("\u{2514}\u{2500}");
self.level = self.level - 1;
}
/// Add an item to the current level in the tree.
fn add_item(&mut self, text: String) {
self.flush_queued_item("\u{251C}\u{2500}");
self.queued_item = Some(text);
}
}
impl Drop for PrintTree {
fn drop(&mut self) {
self.flush_queued_item("\u{9492}\u{9472}");

Просмотреть файл

@ -479,6 +479,10 @@ impl RenderBackend {
let json = self.get_docs_for_debugger();
ResultMsg::DebugOutput(DebugOutput::FetchDocuments(json))
}
DebugCommand::FetchClipScrollTree => {
let json = self.get_clip_scroll_tree_for_debugger();
ResultMsg::DebugOutput(DebugOutput::FetchClipScrollTree(json))
}
_ => {
ResultMsg::DebugCommand(option)
}
@ -596,6 +600,26 @@ impl RenderBackend {
serde_json::to_string(&docs).unwrap()
}
#[cfg(not(feature = "debugger"))]
fn get_clip_scroll_tree_for_debugger(&self) -> String {
String::new()
}
#[cfg(feature = "debugger")]
fn get_clip_scroll_tree_for_debugger(&self) -> String {
let mut debug_root = debug_server::ClipScrollTreeList::new();
for (_, doc) in &self.documents {
let debug_node = debug_server::TreeNode::new("document clip_scroll tree");
let mut builder = debug_server::TreeNodeBuilder::new(debug_node);
doc.frame.clip_scroll_tree.print_with(&mut builder);
debug_root.add(builder.build());
}
serde_json::to_string(&debug_root).unwrap()
}
}
#[cfg(feature = "debugger")]

Просмотреть файл

@ -18,7 +18,7 @@ use debug_colors;
use debug_render::DebugRenderer;
#[cfg(feature = "debugger")]
use debug_server::{self, DebugServer};
use device::{DepthFunction, Device, FrameId, Program, Texture, VertexDescriptor, GpuMarker, GpuProfiler, PBOId};
use device::{DepthFunction, Device, FrameId, Program, Texture, VertexDescriptor, GpuMarker, GpuProfiler, PBO};
use device::{GpuTimer, TextureFilter, VAO, VertexUsageHint, FileWatcherHandler, TextureTarget, ShaderError};
use device::{ExternalTexture, get_gl_format_bgra, TextureSlot, VertexAttribute, VertexAttributeKind};
use euclid::{Transform3D, rect};
@ -499,7 +499,7 @@ impl CacheRow {
/// The device-specific representation of the cache texture in gpu_cache.rs
struct CacheTexture {
texture: Texture,
pbo_id: PBOId,
pbo: PBO,
rows: Vec<CacheRow>,
cpu_blocks: Vec<GpuBlockData>,
}
@ -507,17 +507,18 @@ struct CacheTexture {
impl CacheTexture {
fn new(device: &mut Device) -> CacheTexture {
let texture = device.create_texture(TextureTarget::Default);
let pbo_id = device.create_pbo();
let pbo = device.create_pbo();
CacheTexture {
texture,
pbo_id,
pbo,
rows: Vec::new(),
cpu_blocks: Vec::new(),
}
}
fn deinit(self, device: &mut Device) {
device.delete_pbo(self.pbo);
device.delete_texture(self.texture);
}
@ -584,7 +585,7 @@ impl CacheTexture {
fn flush(&mut self, device: &mut Device) {
// Bind a PBO to do the texture upload.
// Updating the texture via PBO avoids CPU-side driver stalls.
device.bind_pbo(Some(self.pbo_id));
device.bind_pbo(Some(&self.pbo));
for (row_index, row) in self.rows.iter_mut().enumerate() {
if row.is_dirty {
@ -621,7 +622,7 @@ impl CacheTexture {
struct VertexDataTexture {
texture: Texture,
pbo: PBOId,
pbo: PBO,
}
impl VertexDataTexture {
@ -676,7 +677,7 @@ impl VertexDataTexture {
// Bind a PBO to do the texture upload.
// Updating the texture via PBO avoids CPU-side driver stalls.
device.bind_pbo(Some(self.pbo));
device.bind_pbo(Some(&self.pbo));
device.update_pbo_data(data);
device.update_texture_from_pbo(&self.texture,
0,
@ -692,6 +693,7 @@ impl VertexDataTexture {
}
fn deinit(self, device: &mut Device) {
device.delete_pbo(self.pbo);
device.delete_texture(self.texture);
}
}
@ -1002,7 +1004,7 @@ pub struct Renderer {
texture_resolver: SourceTextureResolver,
// A PBO used to do asynchronous texture cache uploads.
texture_cache_upload_pbo: PBOId,
texture_cache_upload_pbo: PBO,
dither_matrix_texture: Option<Texture>,
@ -1619,7 +1621,8 @@ impl Renderer {
}
ResultMsg::DebugOutput(output) => {
match output {
DebugOutput::FetchDocuments(string) => {
DebugOutput::FetchDocuments(string) |
DebugOutput::FetchClipScrollTree(string) => {
self.debug_server.send(string);
}
}
@ -1718,6 +1721,7 @@ impl Renderer {
}
}
DebugCommand::FetchDocuments => {}
DebugCommand::FetchClipScrollTree => {}
DebugCommand::FetchPasses => {
let json = self.get_passes_for_debugger();
self.debug_server.send(json);
@ -1891,7 +1895,7 @@ impl Renderer {
// Bind a PBO to do the texture upload.
// Updating the texture via PBO avoids CPU-side driver stalls.
self.device.bind_pbo(Some(self.texture_cache_upload_pbo));
self.device.bind_pbo(Some(&self.texture_cache_upload_pbo));
match source {
TextureUpdateSource::Bytes { data } => {
@ -1905,6 +1909,16 @@ impl Renderer {
ExternalImageSource::RawData(data) => {
self.device.update_pbo_data(&data[offset as usize..]);
}
ExternalImageSource::Invalid => {
// Create a local buffer to fill the pbo.
let bpp = texture.get_bpp();
let width = stride.unwrap_or(rect.size.width * bpp);
let total_size = width * rect.size.height;
// WR haven't support RGBAF32 format in texture_cache, so
// we use u8 type here.
let dummy_data: Vec<u8> = vec![255; total_size as usize];
self.device.update_pbo_data(&dummy_data);
}
_ => panic!("No external buffer found"),
};
handler.unlock(id, channel_index);
@ -2430,6 +2444,11 @@ impl Renderer {
let texture = match image.source {
ExternalImageSource::NativeTexture(texture_id) => ExternalTexture::new(texture_id, texture_target),
ExternalImageSource::Invalid => {
warn!("Invalid ext-image for ext_id:{:?}, channel:{}.", ext_image.id, ext_image.channel_index);
// Just use 0 as the gl handle for this failed case.
ExternalTexture::new(0, texture_target)
}
_ => panic!("No native texture found."),
};
@ -2758,6 +2777,7 @@ impl Renderer {
for texture in self.color_render_targets {
self.device.delete_texture(texture);
}
self.device.delete_pbo(self.texture_cache_upload_pbo);
self.texture_resolver.deinit(&mut self.device);
self.device.delete_vao(self.prim_vao);
self.device.delete_vao(self.clip_vao);
@ -2803,7 +2823,8 @@ impl Renderer {
pub enum ExternalImageSource<'a> {
RawData(&'a [u8]), // raw buffers.
NativeTexture(u32), // Is a gl::GLuint texture handle
NativeTexture(u32), // It's a gl::GLuint texture handle
Invalid,
}
/// The data that an external client should provide about

Просмотреть файл

@ -267,21 +267,12 @@ pub fn pack_as_float(value: u32) -> f32 {
pub trait ComplexClipRegionHelpers {
/// Return an aligned rectangle that is inside the clip region and doesn't intersect
/// any of the bounding rectangles of the rounded corners.
fn get_inner_rect_safe(&self) -> Option<LayoutRect>;
/// Return the approximately largest aligned rectangle that is fully inside
/// the provided clip region.
fn get_inner_rect_full(&self) -> Option<LayoutRect>;
}
impl ComplexClipRegionHelpers for ComplexClipRegion {
fn get_inner_rect_safe(&self) -> Option<LayoutRect> {
// value of `k==1.0` is used for extraction of the corner rectangles
// see `SEGMENT_CORNER_*` in `clip_shared.glsl`
extract_inner_rect_impl(&self.rect, &self.radii, 1.0)
}
fn get_inner_rect_full(&self) -> Option<LayoutRect> {
// this `k` optimal for a simple case of all border radii being equal
let k = 1.0 - 0.5 * FRAC_1_SQRT_2; // could be nicely approximated to `0.3`
@ -310,6 +301,15 @@ fn extract_inner_rect_impl<U>(rect: &TypedRect<f32, U>,
}
}
/// Return an aligned rectangle that is inside the clip region and doesn't intersect
/// any of the bounding rectangles of the rounded corners.
pub fn extract_inner_rect_safe<U>(rect: &TypedRect<f32, U>,
radii: &BorderRadius) -> Option<TypedRect<f32, U>> {
// value of `k==1.0` is used for extraction of the corner rectangles
// see `SEGMENT_CORNER_*` in `clip_shared.glsl`
extract_inner_rect_impl(rect, radii, 1.0)
}
/// Consumes the old vector and returns a new one that may reuse the old vector's allocated
/// memory.
pub fn recycle_vec<T>(mut old_vec: Vec<T>) -> Vec<T> {

Просмотреть файл

@ -186,6 +186,8 @@ pub enum DebugCommand {
FetchDocuments,
// Fetch current passes and batches.
FetchPasses,
// Fetch clip-scroll tree.
FetchClipScrollTree,
}
#[derive(Clone, Deserialize, Serialize)]

Просмотреть файл

@ -384,23 +384,6 @@ pub enum FilterOp {
Sepia(f32),
}
impl FilterOp {
pub fn is_noop(&self) -> bool {
match *self {
FilterOp::Blur(length) if length == 0.0 => true,
FilterOp::Brightness(amount) if amount == 1.0 => true,
FilterOp::Contrast(amount) if amount == 1.0 => true,
FilterOp::Grayscale(amount) if amount == 0.0 => true,
FilterOp::HueRotate(amount) if amount == 0.0 => true,
FilterOp::Invert(amount) if amount == 0.0 => true,
FilterOp::Opacity(amount) if amount == PropertyBinding::Value(1.0) => true,
FilterOp::Saturate(amount) if amount == 1.0 => true,
FilterOp::Sepia(amount) if amount == 0.0 => true,
_ => false,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct IframeDisplayItem {
pub pipeline_id: PipelineId,