зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1397831 - Update webrender to commit 6cf9cd4075efdf7467bad71b372170f626a8fce4. r=jrmuizel
MozReview-Commit-ID: 8SHrjpb5bKs --HG-- extra : rebase_source : 4718328943014ef62e7cccc566e0fce4c8199073
This commit is contained in:
Родитель
ae53820108
Коммит
f45c53ec90
|
@ -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(®ion.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 ®ion.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 ®ion.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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче