Bug 1353484 - Update webrender to 3dd68f54e12bd5abf8ef41de4d4ec851620f7e4e. r=jrmuizel,kvark,rhunt

This includes:
- updating calls to push_scroll_layer for API change in 7253e2f.
- updating calls to push_stacking_context for API change in be249f6.
- updating for changes to gradient APIs in 05c4293.
This commit is contained in:
Kartikaya Gupta 2017-04-11 10:00:41 -04:00
Родитель 2df2e6a3af
Коммит 59dd9e78bc
43 изменённых файлов: 1296 добавлений и 1250 удалений

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

@ -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: 7463ae5908ca1d4065763a8753af5d72a6f78b85
Latest Commit: 3dd68f54e12bd5abf8ef41de4d4ec851620f7e4e

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

@ -1,6 +1,6 @@
[package]
name = "webrender"
version = "0.30.0"
version = "0.31.0"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"

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

@ -231,16 +231,18 @@ ClipArea fetch_clip_area(int index) {
struct Gradient {
vec4 start_end_point;
vec4 tile_size_repeat;
vec4 extend_mode;
};
Gradient fetch_gradient(int index) {
Gradient gradient;
ivec2 uv = get_fetch_uv_2(index);
ivec2 uv = get_fetch_uv_4(index);
gradient.start_end_point = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
gradient.extend_mode = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));
gradient.start_end_point = texelFetchOffset(sData64, uv, 0, ivec2(0, 0));
gradient.tile_size_repeat = texelFetchOffset(sData64, uv, 0, ivec2(1, 0));
gradient.extend_mode = texelFetchOffset(sData64, uv, 0, ivec2(2, 0));
return gradient;
}
@ -264,15 +266,17 @@ GradientStop fetch_gradient_stop(int index) {
struct RadialGradient {
vec4 start_end_center;
vec4 start_end_radius_ratio_xy_extend_mode;
vec4 tile_size_repeat;
};
RadialGradient fetch_radial_gradient(int index) {
RadialGradient gradient;
ivec2 uv = get_fetch_uv_2(index);
ivec2 uv = get_fetch_uv_4(index);
gradient.start_end_center = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
gradient.start_end_radius_ratio_xy_extend_mode = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));
gradient.start_end_center = texelFetchOffset(sData64, uv, 0, ivec2(0, 0));
gradient.start_end_radius_ratio_xy_extend_mode = texelFetchOffset(sData64, uv, 0, ivec2(1, 0));
gradient.tile_size_repeat = texelFetchOffset(sData64, uv, 0, ivec2(2, 0));
return gradient;
}
@ -763,8 +767,9 @@ vec4 dither(vec4 color) {
const int matrix_mask = 7;
ivec2 pos = ivec2(gl_FragCoord.xy) & ivec2(matrix_mask);
float noise_factor = 4.0 / 255.0;
float noise = texelFetch(sDither, pos, 0).r * noise_factor;
float noise_normalized = (texelFetch(sDither, pos, 0).r * 255.0 + 0.5) / 64.0;
float noise = (noise_normalized - 0.5) / 256.0; // scale down to the unit length
return color + vec4(noise, noise, noise, 0);
}
#endif //WR_FRAGMENT_SHADER

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

@ -5,11 +5,21 @@
uniform sampler2D sGradients;
void main(void) {
vec2 pos = mod(vPos, vTileRepeat);
if (pos.x >= vTileSize.x ||
pos.y >= vTileSize.y) {
discard;
}
// Normalized offset of this vertex within the gradient, before clamp/repeat.
float offset = dot(pos - vStartPoint, vScaledDir);
vec2 texture_size = vec2(textureSize(sGradients, 0));
// Either saturate or modulo the offset depending on repeat mode, then scale to number of
// gradient color entries (texture width / 2).
float x = mix(clamp(vOffset, 0.0, 1.0), fract(vOffset), vGradientRepeat) * 0.5 * texture_size.x;
float x = mix(clamp(offset, 0.0, 1.0), fract(offset), vGradientRepeat) * 0.5 * texture_size.x;
x = 2.0 * floor(x) + 0.5 + fract(x);

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

@ -2,6 +2,10 @@
* 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/. */
flat varying vec2 vScaledDir;
flat varying vec2 vStartPoint;
flat varying float vGradientIndex;
flat varying float vGradientRepeat;
varying float vOffset;
flat varying vec2 vTileSize;
flat varying vec2 vTileRepeat;
varying vec2 vPos;

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

@ -13,18 +13,17 @@ void main(void) {
prim.layer,
prim.task);
// Snap the start/end points to device pixel units.
// I'm not sure this is entirely correct, but the
// old render path does this, and it is needed to
// make the angle gradient ref tests pass. It might
// be better to fix this higher up in DL construction
// and not snap here?
vec2 start_point = floor(0.5 + gradient.start_end_point.xy * uDevicePixelRatio) / uDevicePixelRatio;
vec2 end_point = floor(0.5 + gradient.start_end_point.zw * uDevicePixelRatio) / uDevicePixelRatio;
vPos = vi.local_pos - prim.local_rect.p0;
vec2 start_point = gradient.start_end_point.xy;
vec2 end_point = gradient.start_end_point.zw;
vec2 dir = end_point - start_point;
// Normalized offset of this vertex within the gradient, before clamp/repeat.
vOffset = dot(vi.local_pos - start_point, dir) / dot(dir, dir);
vStartPoint = start_point;
vScaledDir = dir / dot(dir, dir);
vTileSize = gradient.tile_size_repeat.xy;
vTileRepeat = gradient.tile_size_repeat.zw;
// V coordinate of gradient row in lookup texture.
vGradientIndex = float(prim.sub_index);

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

@ -348,6 +348,7 @@ void draw_solid_border(float distanceFromMixLine, vec2 localPos) {
default:
oFragColor = vHorizontalColor;
discard_pixels_in_rounded_borders(localPos);
break;
}
}
@ -427,6 +428,7 @@ void main(void) {
#endif
vec2 brightness_mod = vec2(0.7, 1.3);
bool needs_discard = false;
// Note: we can't pass-through in the following cases,
// because Angle doesn't support it and fails to compile the shaders.
@ -459,9 +461,15 @@ void main(void) {
draw_mixed_border(distance_from_mix_line, distance_from_middle, local_pos, brightness_mod.xy);
break;
case BORDER_STYLE_HIDDEN:
discard;
default:
discard;
needs_discard = true;
break;
}
// Note: Workaround for Angle on Windows,
// because non-empty case statements must have break or return.
if (needs_discard) {
discard;
}
#ifdef WR_FEATURE_TRANSFORM

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

@ -12,9 +12,5 @@ void main(void) {
#endif
alpha = min(alpha, do_clip());
// TODO(gw): Re-enable the gradient dither once we get the
// reftests passing.
//oFragColor = dither(vColor * vec4(1.0, 1.0, 1.0, alpha));
oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
oFragColor = dither(vColor * vec4(1.0, 1.0, 1.0, alpha));
}

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

@ -7,6 +7,8 @@ void main(void) {
Primitive prim = load_primitive();
Gradient gradient = fetch_gradient(prim.prim_index);
vec4 abs_start_end_point = gradient.start_end_point + prim.local_rect.p0.xyxy;
GradientStop g0 = fetch_gradient_stop(prim.sub_index + 0);
GradientStop g1 = fetch_gradient_stop(prim.sub_index + 1);
@ -14,9 +16,9 @@ void main(void) {
vec2 axis;
vec4 adjusted_color_g0 = g0.color;
vec4 adjusted_color_g1 = g1.color;
if (gradient.start_end_point.y == gradient.start_end_point.w) {
if (abs_start_end_point.y == abs_start_end_point.w) {
// Calculate the x coord of the gradient stops
vec2 g01_x = mix(gradient.start_end_point.xx, gradient.start_end_point.zz,
vec2 g01_x = mix(abs_start_end_point.xx, abs_start_end_point.zz,
vec2(g0.offset.x, g1.offset.x));
// The gradient stops might exceed the geometry rect so clamp them
@ -35,7 +37,7 @@ void main(void) {
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
} else {
// Calculate the y coord of the gradient stops
vec2 g01_y = mix(gradient.start_end_point.yy, gradient.start_end_point.ww,
vec2 g01_y = mix(abs_start_end_point.yy, abs_start_end_point.ww,
vec2(g0.offset.x, g1.offset.x));
// The gradient stops might exceed the geometry rect so clamp them

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

@ -5,8 +5,15 @@
uniform sampler2D sGradients;
void main(void) {
vec2 pos = mod(vPos, vTileRepeat);
if (pos.x >= vTileSize.x ||
pos.y >= vTileSize.y) {
discard;
}
vec2 cd = vEndCenter - vStartCenter;
vec2 pd = vPos - vStartCenter;
vec2 pd = pos - vStartCenter;
float rd = vEndRadius - vStartRadius;
// Solve for t in length(t * cd - pd) = vStartRadius + t * rd

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

@ -8,4 +8,6 @@ flat varying vec2 vStartCenter;
flat varying vec2 vEndCenter;
flat varying float vStartRadius;
flat varying float vEndRadius;
flat varying vec2 vTileSize;
flat varying vec2 vTileRepeat;
varying vec2 vPos;

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

@ -13,25 +13,25 @@ void main(void) {
prim.layer,
prim.task);
vPos = vi.local_pos;
vPos = vi.local_pos - prim.local_rect.p0;
vStartCenter = gradient.start_end_center.xy;
vEndCenter = gradient.start_end_center.zw;
// Snap the start/end points to device pixel units.
// I'm not sure this is entirely correct, but the
// old render path does this, and it is needed to
// make the angle gradient ref tests pass. It might
// be better to fix this higher up in DL construction
// and not snap here?
vStartCenter = floor(0.5 + gradient.start_end_center.xy * uDevicePixelRatio) / uDevicePixelRatio;
vEndCenter = floor(0.5 + gradient.start_end_center.zw * uDevicePixelRatio) / uDevicePixelRatio;
vStartRadius = gradient.start_end_radius_ratio_xy_extend_mode.x;
vEndRadius = gradient.start_end_radius_ratio_xy_extend_mode.y;
vTileSize = gradient.tile_size_repeat.xy;
vTileRepeat = gradient.tile_size_repeat.zw;
// Transform all coordinates by the y scale so the
// fragment shader can work with circles
float ratio_xy = gradient.start_end_radius_ratio_xy_extend_mode.z;
vPos.y *= ratio_xy;
vStartCenter.y *= ratio_xy;
vEndCenter.y *= ratio_xy;
vTileSize.y *= ratio_xy;
vTileRepeat.y *= ratio_xy;
// V coordinate of gradient row in lookup texture.
vGradientIndex = float(prim.sub_index);

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

@ -0,0 +1,98 @@
# Clipping in WebRender
The WebRender display list allows defining clips in two different ways. The
first is specified directly on each display item and cannot be reused between
items. The second is specified using the `SpecificDisplayItem::Clip` display item
and can be reused between items as well as used to define scrollable regions.
## Clips
Clips are defined using the ClipRegion in both cases.
```rust
pub struct ClipRegion {
pub main: LayoutRect,
pub complex: ItemRange,
pub image_mask: Option<ImageMask>,
}
```
`main` defines a rectangular clip, while the other members make that rectangle
smaller. `complex`, if it is not empty, defines the boundaries of a rounded
rectangle. While `image_mask` defines the positioning, repetition, and data of
a masking image.
## Item Clips
Item clips are simply a `ClipRegion` structure defined directly on the
`DisplayItem`. The important thing to note about these clips is that all the
coordinate in `ClipRegion` **are in the same coordinate space as the item
itself**. This different than for clips defined by `SpecificDisplayItem::Clip`.
## Clip Display Items
Clip display items allow items to share clips in order to increase performance
(shared clips are only rasterized once) and to allow for scrolling regions.
Display items can be assigned a clip display item using the `scroll_layer_id`
field. An item can be assigned any clip that is defined by its parent stacking
context or any of the ancestors. The behavior of assigning an id outside of
this hierarchy is undefined, because that situation does not occur in CSS
The clip display item has a `ClipRegion` as well as several other fields:
```rust
pub struct ClipDisplayItem {
pub id: ScrollLayerId,
pub parent_id: ScrollLayerId,
}
```
A `ClipDisplayItem` also gets a clip and bounds from the `BaseDisplayItem`. The
clip is shared among all items that use this `ClipDisplayItem`. Critically,
**coordinates in this ClipRegion are defined relative to the bounds of the
ClipDisplayItem itself**. Additionally, WebRender only supports clip rectangles
that start at the origin of the `BaseDisplayItem` bounds.
The `BaseDisplayItem` bounds are known as the *content rectangle* of the clip. If
the content rectangle is larger than *main* clipping rectangle, the clip will
be a scrolling clip and participate in scrolling event capture and
transformation.
`ClipDisplayItems` are positioned, like all other items, relatively to their
containing stacking context, yet they also live in a parallel tree defined by
their `parent_id`. Child clips also include any clipping and scrolling that
their ancestors do. In this way, a clip is positioned by a stacking context,
but that position may be adjusted by any scroll offset of its parent clips.
## Clip ids
All clips defined by a `ClipDisplayItem` have an id. It is useful to associate
an external id with WebRender id in order to allow for tracking and updating
scroll positions using the WebRender API. In order to make this as cheap as
possible and to avoid having to create a `HashMap` to map between the two types
of ids, the WebRender API provides an optional id argument in
`DisplayListBuilder::define_clip`. The only types of ids that are supported
here are those created with `ScrollLayerId::new(...)`. If this argument is not
provided `define_clip` will return a uniquely generated id. Thus, the following
should always be true:
```rust
let id = ScrollLayerId::new(my_internal_id, pipeline_id);
let generated_id = define_clip(content_rect, clip, id);
assert!(id == generated_id);
```
## Pending changes
1. Rename `ScrollLayerId` to `ClipId`. The current name is a holdover from the
previous design. ([github issue](https://github.com/servo/webrender/issues/1089))
2. Normalize the way that clipping coordinates are defined. Having them
specified in two different ways makes for a confusing API. This should be
fixed. ([github issue](https://github.com/servo/webrender/issues/1090))
3. It should be possible to specify more than one predefined clip for an item.
This is necessary for items that live in a scrolling frame, but are also
clipped by a clip that lives outside that frame.
([github issue](https://github.com/servo/webrender/issues/840))

202
gfx/webrender/src/border.rs Normal file
Просмотреть файл

@ -0,0 +1,202 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 frame_builder::FrameBuilder;
use tiling::PrimitiveFlags;
use webrender_traits::{BorderSide, BorderStyle, BorderWidths, NormalBorder};
use webrender_traits::{ClipRegion, LayerPoint, LayerRect, LayerSize, ScrollLayerId};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BorderCornerKind {
None,
Solid,
Complex,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BorderEdgeKind {
None,
Solid,
Complex,
}
pub trait NormalBorderHelpers {
fn get_corner(&self,
edge0: &BorderSide,
width0: f32,
edge1: &BorderSide,
width1: f32,
radius: &LayerSize) -> BorderCornerKind;
fn get_edge(&self,
edge: &BorderSide,
width: f32) -> (BorderEdgeKind, f32);
}
impl NormalBorderHelpers for NormalBorder {
fn get_corner(&self,
edge0: &BorderSide,
width0: f32,
edge1: &BorderSide,
width1: f32,
radius: &LayerSize) -> BorderCornerKind {
// If either width is zero, a corner isn't formed.
if width0 == 0.0 || width1 == 0.0 {
return BorderCornerKind::None;
}
// If both edges are transparent, no corner is formed.
if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
return BorderCornerKind::None;
}
match (edge0.style, edge1.style) {
// If either edge is none or hidden, no corner is needed.
(BorderStyle::None, _) | (_, BorderStyle::None) => BorderCornerKind::None,
(BorderStyle::Hidden, _) | (_, BorderStyle::Hidden) => BorderCornerKind::None,
// If both borders are solid, we can draw them with a simple rectangle if
// both the colors match and there is no radius.
(BorderStyle::Solid, BorderStyle::Solid) => {
if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
BorderCornerKind::Solid
} else {
BorderCornerKind::Complex
}
}
// Assume complex for these cases.
// TODO(gw): There are some cases in here that can be handled with a fast path.
// For example, with inset/outset borders, two of the four corners are solid.
(BorderStyle::Dotted, _) | (_, BorderStyle::Dotted) => BorderCornerKind::Complex,
(BorderStyle::Dashed, _) | (_, BorderStyle::Dashed) => BorderCornerKind::Complex,
(BorderStyle::Double, _) | (_, BorderStyle::Double) => BorderCornerKind::Complex,
(BorderStyle::Groove, _) | (_, BorderStyle::Groove) => BorderCornerKind::Complex,
(BorderStyle::Ridge, _) | (_, BorderStyle::Ridge) => BorderCornerKind::Complex,
(BorderStyle::Outset, _) | (_, BorderStyle::Outset) => BorderCornerKind::Complex,
(BorderStyle::Inset, _) | (_, BorderStyle::Inset) => BorderCornerKind::Complex,
}
}
fn get_edge(&self,
edge: &BorderSide,
width: f32) -> (BorderEdgeKind, f32) {
if width == 0.0 {
return (BorderEdgeKind::None, 0.0);
}
match edge.style {
BorderStyle::None |
BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),
BorderStyle::Solid |
BorderStyle::Inset |
BorderStyle::Outset => (BorderEdgeKind::Solid, width),
BorderStyle::Double |
BorderStyle::Dotted |
BorderStyle::Dashed |
BorderStyle::Groove |
BorderStyle::Ridge => (BorderEdgeKind::Complex, width),
}
}
}
impl FrameBuilder {
// TODO(gw): This allows us to move border types over to the
// simplified shader model one at a time. Once all borders
// are converted, this can be removed, along with the complex
// border code path.
pub fn add_simple_border(&mut self,
rect: &LayerRect,
border: &NormalBorder,
widths: &BorderWidths,
scroll_layer_id: ScrollLayerId,
clip_region: &ClipRegion) -> bool {
// The border shader is quite expensive. For simple borders, we can just draw
// the border with a few rectangles. This generally gives better batching, and
// a GPU win in fragment shader time.
// More importantly, the software (OSMesa) implementation we run tests on is
// particularly slow at running our complex border shader, compared to the
// rectangle shader. This has the effect of making some of our tests time
// out more often on CI (the actual cause is simply too many Servo processes and
// threads being run on CI at once).
let radius = &border.radius;
let left = &border.left;
let right = &border.right;
let top = &border.top;
let bottom = &border.bottom;
// If any of the corners are complex, fall back to slow path for now.
let tl = border.get_corner(left, widths.left, top, widths.top, &radius.top_left);
let tr = border.get_corner(top, widths.top, right, widths.right, &radius.top_right);
let br = border.get_corner(right, widths.right, bottom, widths.bottom, &radius.bottom_right);
let bl = border.get_corner(bottom, widths.bottom, left, widths.left, &radius.bottom_left);
if tl == BorderCornerKind::Complex ||
tr == BorderCornerKind::Complex ||
br == BorderCornerKind::Complex ||
bl == BorderCornerKind::Complex {
return false;
}
// If any of the edges are complex, fall back to slow path for now.
let (left_edge, left_len) = border.get_edge(left, widths.left);
let (top_edge, top_len) = border.get_edge(top, widths.top);
let (right_edge, right_len) = border.get_edge(right, widths.right);
let (bottom_edge, bottom_len) = border.get_edge(bottom, widths.bottom);
if left_edge == BorderEdgeKind::Complex ||
top_edge == BorderEdgeKind::Complex ||
right_edge == BorderEdgeKind::Complex ||
bottom_edge == BorderEdgeKind::Complex {
return false;
}
let p0 = rect.origin;
let p1 = rect.bottom_right();
let rect_width = rect.size.width;
let rect_height = rect.size.height;
// Add a solid rectangle for each visible edge/corner combination.
if top_edge == BorderEdgeKind::Solid {
self.add_solid_rectangle(scroll_layer_id,
&LayerRect::new(p0,
LayerSize::new(rect.size.width, top_len)),
clip_region,
&border.top.color,
PrimitiveFlags::None);
}
if left_edge == BorderEdgeKind::Solid {
self.add_solid_rectangle(scroll_layer_id,
&LayerRect::new(LayerPoint::new(p0.x, p0.y + top_len),
LayerSize::new(left_len,
rect_height - top_len - bottom_len)),
clip_region,
&border.left.color,
PrimitiveFlags::None);
}
if right_edge == BorderEdgeKind::Solid {
self.add_solid_rectangle(scroll_layer_id,
&LayerRect::new(LayerPoint::new(p1.x - right_len,
p0.y + top_len),
LayerSize::new(right_len,
rect_height - top_len - bottom_len)),
clip_region,
&border.right.color,
PrimitiveFlags::None);
}
if bottom_edge == BorderEdgeKind::Solid {
self.add_solid_rectangle(scroll_layer_id,
&LayerRect::new(LayerPoint::new(p0.x, p1.y - bottom_len),
LayerSize::new(rect_width, bottom_len)),
clip_region,
&border.bottom.color,
PrimitiveFlags::None);
}
true
}
}

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

@ -118,15 +118,18 @@ pub struct ClipScrollNode {
impl ClipScrollNode {
pub fn new(pipeline_id: PipelineId,
parent_id: ScrollLayerId,
local_viewport_rect: &LayerRect,
content_size: LayerSize,
content_rect: &LayerRect,
clip_rect: &LayerRect,
clip_info: ClipInfo)
-> ClipScrollNode {
// FIXME(mrobinson): We don't yet handle clipping rectangles that don't start at the origin
// of the node.
let local_viewport_rect = LayerRect::new(content_rect.origin, clip_rect.size);
ClipScrollNode {
scrolling: ScrollingState::new(),
content_size: content_size,
local_viewport_rect: *local_viewport_rect,
local_clip_rect: *local_viewport_rect,
content_size: content_rect.size,
local_viewport_rect: local_viewport_rect,
local_clip_rect: local_viewport_rect,
combined_local_viewport_rect: LayerRect::zero(),
world_viewport_transform: LayerToWorldTransform::identity(),
world_content_transform: LayerToWorldTransform::identity(),
@ -213,7 +216,7 @@ impl ClipScrollNode {
self.scrolling.offset = new_offset;
self.scrolling.bouncing_back = false;
self.scrolling.started_bouncing_back = false;
return true;
true
}
pub fn update_transform(&mut self,

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

@ -292,14 +292,14 @@ impl ClipScrollTree {
// TODO(gw): These are all independent - can be run through thread pool if it shows up
// in the profile!
for (scroll_layer_id, node) in &mut self.nodes {
let scrolling_state = match old_states.get(&scroll_layer_id) {
let scrolling_state = match old_states.get(scroll_layer_id) {
Some(old_scrolling_state) => *old_scrolling_state,
None => ScrollingState::new(),
};
node.finalize(&scrolling_state);
if let Some(pending_offset) = self.pending_scroll_offsets.remove(&scroll_layer_id) {
if let Some(pending_offset) = self.pending_scroll_offsets.remove(scroll_layer_id) {
node.set_scroll_origin(&pending_offset);
}
}
@ -318,9 +318,9 @@ impl ClipScrollTree {
self.current_reference_frame_id += 1;
let node = ClipScrollNode::new_reference_frame(parent_id,
&rect,
rect,
rect.size,
&transform,
transform,
pipeline_id);
self.add_node(node, reference_frame_id);
reference_frame_id

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

@ -676,10 +676,10 @@ impl<T> GpuProfiler<T> {
GpuProfiler {
next_frame: 0,
frames: [
GpuFrameProfile::new(gl.clone()),
GpuFrameProfile::new(gl.clone()),
GpuFrameProfile::new(gl.clone()),
GpuFrameProfile::new(gl.clone()),
GpuFrameProfile::new(Rc::clone(gl)),
GpuFrameProfile::new(Rc::clone(gl)),
GpuFrameProfile::new(Rc::clone(gl)),
GpuFrameProfile::new(Rc::clone(gl)),
],
}
}
@ -721,12 +721,12 @@ impl GpuMarker {
gl::GlType::Gl => {
gl.push_group_marker_ext(message);
GpuMarker{
gl: gl.clone(),
gl: Rc::clone(gl),
}
}
gl::GlType::Gles => {
GpuMarker{
gl: gl.clone(),
gl: Rc::clone(gl),
}
}
}
@ -973,7 +973,7 @@ impl Device {
let mut s = String::new();
s.push_str(get_shader_version(gl));
for prefix in shader_preamble {
s.push_str(&prefix);
s.push_str(prefix);
}
s.push_str(source_str);
@ -1108,7 +1108,7 @@ impl Device {
};
let texture = Texture {
gl: self.gl.clone(),
gl: Rc::clone(&self.gl),
id: id,
width: 0,
height: 0,
@ -1451,7 +1451,7 @@ impl Device {
}
let program = Program {
gl: self.gl.clone(),
gl: Rc::clone(&self.gl),
name: base_filename.to_owned(),
id: pid,
u_transform: -1,
@ -1795,7 +1795,7 @@ impl Device {
ibo_id.bind(self.gl()); // force it to be a part of VAO
let vao = VAO {
gl: self.gl.clone(),
gl: Rc::clone(&self.gl),
id: vao_id,
ibo_id: ibo_id,
main_vbo_id: main_vbo_id,
@ -1851,7 +1851,7 @@ impl Device {
debug_assert_eq!(self.bound_vao, vao_id);
vao.main_vbo_id.bind(self.gl());
gl::buffer_data(self.gl(), gl::ARRAY_BUFFER, &vertices, usage_hint.to_gl());
gl::buffer_data(self.gl(), gl::ARRAY_BUFFER, vertices, usage_hint.to_gl());
}
pub fn update_vao_instances<V>(&mut self,
@ -1865,7 +1865,7 @@ impl Device {
debug_assert_eq!(vao.instance_stride as usize, mem::size_of::<V>());
vao.instance_vbo_id.bind(self.gl());
gl::buffer_data(self.gl(), gl::ARRAY_BUFFER, &instances, usage_hint.to_gl());
gl::buffer_data(self.gl(), gl::ARRAY_BUFFER, instances, usage_hint.to_gl());
}
pub fn update_vao_indices<I>(&mut self,
@ -1878,7 +1878,7 @@ impl Device {
debug_assert_eq!(self.bound_vao, vao_id);
vao.ibo_id.bind(self.gl());
gl::buffer_data(self.gl(), gl::ELEMENT_ARRAY_BUFFER, &indices, usage_hint.to_gl());
gl::buffer_data(self.gl(), gl::ELEMENT_ARRAY_BUFFER, indices, usage_hint.to_gl());
}
pub fn draw_triangles_u16(&mut self, first_vertex: i32, index_count: i32) {

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

@ -16,7 +16,7 @@ use scene::{Scene, SceneProperties};
use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use tiling::{AuxiliaryListsMap, CompositeOps, PrimitiveFlags};
use util::subtract_rect;
use util::{ComplexClipRegionHelpers, subtract_rect};
use webrender_traits::{AuxiliaryLists, ClipDisplayItem, ClipRegion, ColorF, DeviceUintRect};
use webrender_traits::{DeviceUintSize, DisplayItem, Epoch, FilterOp, ImageDisplayItem, LayerPoint};
use webrender_traits::{LayerRect, LayerSize, LayerToScrollTransform, LayoutRect, LayoutTransform};
@ -217,7 +217,7 @@ fn clip_intersection(original_rect: &LayerRect,
let base_rect = region.main.intersection(original_rect);
clips.iter().fold(base_rect, |inner_combined, ccr| {
inner_combined.and_then(|combined| {
ccr.get_inner_rect().and_then(|ir| ir.intersection(&combined))
ccr.get_inner_rect_full().and_then(|ir| ir.intersection(&combined))
})
})
}
@ -341,8 +341,8 @@ impl Frame {
scroll_layer_id,
LayerPoint::zero(),
0,
&root_bounds,
&root_stacking_context);
root_bounds,
root_stacking_context);
}
self.frame_builder = Some(frame_builder);
@ -354,14 +354,12 @@ impl Frame {
pipeline_id: PipelineId,
parent_id: ScrollLayerId,
item: &ClipDisplayItem,
reference_frame_relative_offset: LayerPoint,
content_rect: &LayerRect,
clip: &ClipRegion) {
let clip_rect = clip.main.translate(&reference_frame_relative_offset);
context.builder.add_clip_scroll_node(item.id,
parent_id,
pipeline_id,
&clip_rect,
&item.content_size,
&content_rect,
clip,
&mut self.clip_scroll_tree);
@ -439,7 +437,8 @@ impl Frame {
context.builder.push_stacking_context(&reference_frame_relative_offset,
pipeline_id,
level == 0,
composition_operations);
composition_operations,
stacking_context.transform_style);
// For the root pipeline, there's no need to add a full screen rectangle
// here, as it's handled by the framebuffer clear.
@ -450,7 +449,7 @@ impl Frame {
// it's already processed by the node we just pushed.
let background_rect = LayerRect::new(LayerPoint::zero(), bounds.size);
context.builder.add_solid_rectangle(scroll_layer_id,
&bounds,
bounds,
&ClipRegion::simple(&background_rect),
&bg_color,
PrimitiveFlags::None);
@ -492,7 +491,6 @@ impl Frame {
bounds: &LayerRect,
context: &mut FlattenContext,
reference_frame_relative_offset: LayerPoint) {
let pipeline = match context.scene.pipeline_map.get(&pipeline_id) {
Some(pipeline) => pipeline,
None => return,
@ -533,9 +531,8 @@ impl Frame {
iframe_scroll_layer_id,
iframe_reference_frame_id,
pipeline_id,
&LayerRect::new(LayerPoint::zero(), iframe_rect.size),
&iframe_stacking_context_bounds.size,
&ClipRegion::simple(&iframe_stacking_context_bounds),
&LayerRect::new(LayerPoint::zero(), iframe_stacking_context_bounds.size),
&ClipRegion::simple(&iframe_rect),
&mut self.clip_scroll_tree);
let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
@ -545,8 +542,8 @@ impl Frame {
iframe_scroll_layer_id,
LayerPoint::zero(),
0,
&iframe_stacking_context_bounds,
&iframe_stacking_context);
iframe_stacking_context_bounds,
iframe_stacking_context);
context.builder.pop_reference_frame();
}
@ -616,7 +613,7 @@ impl Frame {
.get(&pipeline_id)
.expect("No auxiliary lists?!");
// Try to extract the opaque inner rectangle out of the clipped primitive.
if let Some(opaque_rect) = clip_intersection(&item.rect, &item.clip, &auxiliary_lists) {
if let Some(opaque_rect) = clip_intersection(&item.rect, &item.clip, auxiliary_lists) {
let mut results = Vec::new();
subtract_rect(&item.rect, &opaque_rect, &mut results);
// The inner rectangle is considered opaque within this layer.
@ -648,7 +645,9 @@ impl Frame {
info.gradient.start_point,
info.gradient.end_point,
info.gradient.stops,
info.gradient.extend_mode);
info.gradient.extend_mode,
info.tile_size,
info.tile_spacing);
}
SpecificDisplayItem::RadialGradient(ref info) => {
context.builder.add_radial_gradient(scroll_layer_id,
@ -660,7 +659,9 @@ impl Frame {
info.gradient.end_radius,
info.gradient.ratio_xy,
info.gradient.stops,
info.gradient.extend_mode);
info.gradient.extend_mode,
info.tile_size,
info.tile_spacing);
}
SpecificDisplayItem::BoxShadow(ref box_shadow_info) => {
context.builder.add_box_shadow(scroll_layer_id,
@ -697,11 +698,12 @@ impl Frame {
reference_frame_relative_offset);
}
SpecificDisplayItem::Clip(ref info) => {
let content_rect = &item.rect.translate(&reference_frame_relative_offset);
self.flatten_clip(context,
pipeline_id,
scroll_layer_id,
&info,
reference_frame_relative_offset,
&content_rect,
&item.clip);
}
SpecificDisplayItem::PopStackingContext => return,
@ -744,7 +746,7 @@ impl Frame {
item_rect.origin.y + (i as f32) * layout_stride,
item_rect.size.width,
info.stretch_size.height
).intersection(&item_rect) {
).intersection(item_rect) {
self.decompose_image_row(scroll_layer_id, context, &row_rect, item_clip, info, image_size, tile_size);
}
}
@ -774,7 +776,7 @@ impl Frame {
item_rect.origin.y,
info.stretch_size.width,
item_rect.size.height,
).intersection(&item_rect) {
).intersection(item_rect) {
self.decompose_tiled_image(scroll_layer_id, context, &decomposed_rect, item_clip, info, image_size, tile_size);
}
}
@ -963,10 +965,10 @@ impl Frame {
}
// Fix up the primitive's rect if it overflows the original item rect.
if let Some(prim_rect) = prim_rect.intersection(&item_rect) {
if let Some(prim_rect) = prim_rect.intersection(item_rect) {
context.builder.add_image(scroll_layer_id,
prim_rect,
&item_clip,
item_clip,
&stretched_size,
&info.tile_spacing,
None,

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

@ -26,14 +26,15 @@ use tiling::StackingContextIndex;
use tiling::{AuxiliaryListsMap, ClipScrollGroup, ClipScrollGroupIndex, CompositeOps, Frame};
use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, RenderPass};
use tiling::{RenderTargetContext, RenderTaskCollection, ScrollbarPrimitive, StackingContext};
use util::{self, pack_as_float, rect_from_points_f, subtract_rect};
use util::{RectHelpers, TransformedRectKind};
use webrender_traits::{BorderDetails, BorderDisplayItem, BorderSide, BorderStyle};
use util::{self, pack_as_float, subtract_rect};
use util::RectHelpers;
use webrender_traits::{BorderDetails, BorderDisplayItem};
use webrender_traits::{BoxShadowClipMode, ClipRegion, ColorF, DeviceIntPoint, DeviceIntRect};
use webrender_traits::{DeviceIntSize, DeviceUintRect, DeviceUintSize, ExtendMode, FontKey};
use webrender_traits::{FontRenderMode, GlyphOptions, ImageKey, ImageRendering, ItemRange};
use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, PipelineId};
use webrender_traits::{RepeatMode, ScrollLayerId, TileOffset, WebGLContextId, YuvColorSpace};
use webrender_traits::{TransformStyle};
#[derive(Debug, Clone)]
struct ImageBorderSegment {
@ -219,7 +220,8 @@ impl FrameBuilder {
reference_frame_offset: &LayerPoint,
pipeline_id: PipelineId,
is_page_root: bool,
composite_ops: CompositeOps) {
composite_ops: CompositeOps,
transform_style: TransformStyle) {
if let Some(parent_index) = self.stacking_context_stack.last() {
let parent_is_root = self.stacking_context_store[parent_index.0].is_page_root;
@ -235,6 +237,7 @@ impl FrameBuilder {
self.stacking_context_store.push(StackingContext::new(pipeline_id,
*reference_frame_offset,
is_page_root,
transform_style,
composite_ops));
self.cmds.push(PrimitiveRunCmd::PushStackingContext(stacking_context_index));
self.stacking_context_stack.push(stacking_context_index);
@ -309,8 +312,7 @@ impl FrameBuilder {
self.add_clip_scroll_node(topmost_scroll_layer_id,
clip_scroll_tree.root_reference_frame_id,
pipeline_id,
&viewport_rect,
content_size,
&LayerRect::new(LayerPoint::zero(), *content_size),
&ClipRegion::simple(&viewport_rect),
clip_scroll_tree);
topmost_scroll_layer_id
@ -320,8 +322,7 @@ impl FrameBuilder {
new_node_id: ScrollLayerId,
parent_id: ScrollLayerId,
pipeline_id: PipelineId,
local_viewport_rect: &LayerRect,
content_size: &LayerSize,
content_rect: &LayerRect,
clip_region: &ClipRegion,
clip_scroll_tree: &mut ClipScrollTree) {
let clip_info = ClipInfo::new(clip_region,
@ -329,8 +330,8 @@ impl FrameBuilder {
PackedLayerIndex(self.packed_layers.len()));
let node = ClipScrollNode::new(pipeline_id,
parent_id,
local_viewport_rect,
*content_size,
content_rect,
&clip_region.main,
clip_info);
clip_scroll_tree.add_node(node, new_node_id);
@ -373,26 +374,6 @@ impl FrameBuilder {
}
}
pub fn supported_style(&mut self, border: &BorderSide) -> bool {
match border.style {
BorderStyle::Solid |
BorderStyle::None |
BorderStyle::Dotted |
BorderStyle::Dashed |
BorderStyle::Inset |
BorderStyle::Ridge |
BorderStyle::Groove |
BorderStyle::Outset |
BorderStyle::Double => {
return true;
}
_ => {
println!("TODO: Other border styles {:?}", border.style);
return false;
}
}
}
pub fn add_border(&mut self,
scroll_layer_id: ScrollLayerId,
rect: LayerRect,
@ -542,96 +523,30 @@ impl FrameBuilder {
}
}
BorderDetails::Normal(ref border) => {
// Gradually move border types over to a simplified
// shader and code path that can handle all border
// cases correctly.
if self.add_simple_border(&rect,
border,
&border_item.widths,
scroll_layer_id,
clip_region) {
return;
}
let radius = &border.radius;
let left = &border.left;
let right = &border.right;
let top = &border.top;
let bottom = &border.bottom;
if !self.supported_style(left) || !self.supported_style(right) ||
!self.supported_style(top) || !self.supported_style(bottom) {
println!("Unsupported border style, not rendering border");
return;
}
// These colors are used during inset/outset scaling.
let left_color = left.border_color(1.0, 2.0/3.0, 0.3, 0.7);
let top_color = top.border_color(1.0, 2.0/3.0, 0.3, 0.7);
let right_color = right.border_color(2.0/3.0, 1.0, 0.7, 0.3);
let bottom_color = bottom.border_color(2.0/3.0, 1.0, 0.7, 0.3);
let tl_outer = LayerPoint::new(rect.origin.x, rect.origin.y);
let tl_inner = tl_outer + LayerPoint::new(radius.top_left.width.max(border_item.widths.left),
radius.top_left.height.max(border_item.widths.top));
let tr_outer = LayerPoint::new(rect.origin.x + rect.size.width, rect.origin.y);
let tr_inner = tr_outer + LayerPoint::new(-radius.top_right.width.max(border_item.widths.right),
radius.top_right.height.max(border_item.widths.top));
let bl_outer = LayerPoint::new(rect.origin.x, rect.origin.y + rect.size.height);
let bl_inner = bl_outer + LayerPoint::new(radius.bottom_left.width.max(border_item.widths.left),
-radius.bottom_left.height.max(border_item.widths.bottom));
let br_outer = LayerPoint::new(rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
let br_inner = br_outer - LayerPoint::new(radius.bottom_right.width.max(border_item.widths.right),
radius.bottom_right.height.max(border_item.widths.bottom));
// The border shader is quite expensive. For simple borders, we can just draw
// the border with a few rectangles. This generally gives better batching, and
// a GPU win in fragment shader time.
// More importantly, the software (OSMesa) implementation we run tests on is
// particularly slow at running our complex border shader, compared to the
// rectangle shader. This has the effect of making some of our tests time
// out more often on CI (the actual cause is simply too many Servo processes and
// threads being run on CI at once).
// TODO(gw): Detect some more simple cases and handle those with simpler shaders too.
// TODO(gw): Consider whether it's only worth doing this for large rectangles (since
// it takes a little more CPU time to handle multiple rectangles compared
// to a single border primitive).
if left.style == BorderStyle::Solid {
let same_color = left_color == top_color &&
left_color == right_color &&
left_color == bottom_color;
let same_style = left.style == top.style &&
left.style == right.style &&
left.style == bottom.style;
if same_color && same_style && radius.is_zero() {
let rects = [
LayerRect::new(rect.origin,
LayerSize::new(rect.size.width, border_item.widths.top)),
LayerRect::new(LayerPoint::new(tl_outer.x, tl_inner.y),
LayerSize::new(border_item.widths.left,
rect.size.height - border_item.widths.top - border_item.widths.bottom)),
LayerRect::new(tr_inner,
LayerSize::new(border_item.widths.right,
rect.size.height - border_item.widths.top - border_item.widths.bottom)),
LayerRect::new(LayerPoint::new(bl_outer.x, bl_inner.y),
LayerSize::new(rect.size.width, border_item.widths.bottom))
];
for rect in &rects {
self.add_solid_rectangle(scroll_layer_id,
rect,
clip_region,
&top_color,
PrimitiveFlags::None);
}
return;
}
}
//Note: while similar to `ComplexClipRegion::get_inner_rect()` in spirit,
// this code is a bit more complex and can not there for be merged.
let inner_rect = rect_from_points_f(tl_inner.x.max(bl_inner.x),
tl_inner.y.max(tr_inner.y),
tr_inner.x.min(br_inner.x),
bl_inner.y.min(br_inner.y));
let prim_cpu = BorderPrimitiveCpu {
inner_rect: LayerRect::from_untyped(&inner_rect),
};
let prim_gpu = BorderPrimitiveGpu {
@ -662,27 +577,35 @@ impl FrameBuilder {
}
BorderDetails::Gradient(ref border) => {
for segment in create_segments(border.outset) {
let segment_rel = segment.origin - rect.origin;
self.add_gradient(scroll_layer_id,
segment,
clip_region,
border.gradient.start_point,
border.gradient.end_point,
border.gradient.start_point - segment_rel,
border.gradient.end_point - segment_rel,
border.gradient.stops,
border.gradient.extend_mode);
border.gradient.extend_mode,
segment.size,
LayerSize::zero());
}
}
BorderDetails::RadialGradient(ref border) => {
for segment in create_segments(border.outset) {
let segment_rel = segment.origin - rect.origin;
self.add_radial_gradient(scroll_layer_id,
segment,
clip_region,
border.gradient.start_center,
border.gradient.start_center - segment_rel,
border.gradient.start_radius,
border.gradient.end_center,
border.gradient.end_center - segment_rel,
border.gradient.end_radius,
border.gradient.ratio_xy,
border.gradient.stops,
border.gradient.extend_mode);
border.gradient.extend_mode,
segment.size,
LayerSize::zero());
}
}
}
@ -695,15 +618,23 @@ impl FrameBuilder {
start_point: LayerPoint,
end_point: LayerPoint,
stops: ItemRange,
extend_mode: ExtendMode) {
// Fast path for clamped, axis-aligned gradients:
let aligned = extend_mode == ExtendMode::Clamp &&
(start_point.x == end_point.x &&
start_point.x.min(end_point.x) <= rect.min_x() &&
start_point.x.max(end_point.x) >= rect.max_x()) ||
(start_point.y == end_point.y &&
start_point.y.min(end_point.y) <= rect.min_y() &&
start_point.y.max(end_point.y) >= rect.max_y());
extend_mode: ExtendMode,
tile_size: LayerSize,
tile_spacing: LayerSize) {
let tile_repeat = tile_size + tile_spacing;
let is_not_tiled = tile_repeat.width >= rect.size.width &&
tile_repeat.height >= rect.size.height;
let aligned_and_fills_rect = (start_point.x == end_point.x &&
start_point.y.min(end_point.y) <= 0.0 &&
start_point.y.max(end_point.y) >= rect.size.height) ||
(start_point.y == end_point.y &&
start_point.x.min(end_point.x) <= 0.0 &&
start_point.x.max(end_point.x) >= rect.size.width);
// Fast path for clamped, axis-aligned gradients, with gradient lines intersecting all of rect:
let aligned = extend_mode == ExtendMode::Clamp && is_not_tiled && aligned_and_fills_rect;
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
// are also supplied in reverse that the rendered result will be equivalent. To do this,
// a reference orientation for the gradient line must be chosen, somewhat arbitrarily, so
@ -735,7 +666,9 @@ impl FrameBuilder {
start_point: sp,
end_point: ep,
extend_mode: pack_as_float(extend_mode as u32),
padding: [0.0, 0.0, 0.0],
tile_size: tile_size,
tile_repeat: tile_repeat,
padding: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
};
let prim = if aligned {
@ -761,7 +694,9 @@ impl FrameBuilder {
end_radius: f32,
ratio_xy: f32,
stops: ItemRange,
extend_mode: ExtendMode) {
extend_mode: ExtendMode,
tile_size: LayerSize,
tile_spacing: LayerSize) {
let radial_gradient_cpu = RadialGradientPrimitiveCpu {
stops_range: stops,
extend_mode: extend_mode,
@ -775,6 +710,9 @@ impl FrameBuilder {
end_radius: end_radius,
ratio_xy: ratio_xy,
extend_mode: pack_as_float(extend_mode as u32),
tile_size: tile_size,
tile_repeat: tile_size + tile_spacing,
padding: [0.0, 0.0, 0.0, 0.0],
};
self.add_primitive(scroll_layer_id,
@ -802,57 +740,39 @@ impl FrameBuilder {
return
}
let (render_mode, glyphs_per_run) = if blur_radius == Au(0) {
// TODO(gw): Use a proper algorithm to select
// whether this item should be rendered with
// subpixel AA!
let render_mode = if self.config.enable_subpixel_aa {
FontRenderMode::Subpixel
} else {
FontRenderMode::Alpha
};
(render_mode, 8)
// TODO(gw): Use a proper algorithm to select
// whether this item should be rendered with
// subpixel AA!
let render_mode = if blur_radius == Au(0) &&
self.config.enable_subpixel_aa {
FontRenderMode::Subpixel
} else {
// TODO(gw): Support breaking up text shadow when
// the size of the text run exceeds the dimensions
// of the render target texture.
(FontRenderMode::Alpha, glyph_range.length)
FontRenderMode::Alpha
};
let text_run_count = (glyph_range.length + glyphs_per_run - 1) / glyphs_per_run;
for run_index in 0..text_run_count {
let start = run_index * glyphs_per_run;
let end = cmp::min(start + glyphs_per_run, glyph_range.length);
let sub_range = ItemRange {
start: glyph_range.start + start,
length: end - start,
};
let prim_cpu = TextRunPrimitiveCpu {
font_key: font_key,
logical_font_size: size,
blur_radius: blur_radius,
glyph_range: glyph_range,
cache_dirty: true,
glyph_instances: Vec::new(),
color_texture_id: SourceTexture::Invalid,
color: *color,
render_mode: render_mode,
glyph_options: glyph_options,
resource_address: GpuStoreAddress(0),
};
let prim_cpu = TextRunPrimitiveCpu {
font_key: font_key,
logical_font_size: size,
blur_radius: blur_radius,
glyph_range: sub_range,
cache_dirty: true,
glyph_instances: Vec::new(),
color_texture_id: SourceTexture::Invalid,
color: *color,
render_mode: render_mode,
glyph_options: glyph_options,
resource_address: GpuStoreAddress(0),
};
let prim_gpu = TextRunPrimitiveGpu {
color: *color,
};
let prim_gpu = TextRunPrimitiveGpu {
color: *color,
};
self.add_primitive(scroll_layer_id,
&rect,
clip_region,
None,
PrimitiveContainer::TextRun(prim_cpu, prim_gpu));
}
self.add_primitive(scroll_layer_id,
&rect,
clip_region,
None,
PrimitiveContainer::TextRun(prim_cpu, prim_gpu));
}
pub fn add_box_shadow(&mut self,
@ -872,7 +792,7 @@ impl FrameBuilder {
// Fast path.
if blur_radius == 0.0 && spread_radius == 0.0 && clip_mode == BoxShadowClipMode::None {
self.add_solid_rectangle(scroll_layer_id,
&box_bounds,
box_bounds,
clip_region,
color,
PrimitiveFlags::None);
@ -967,12 +887,17 @@ impl FrameBuilder {
BoxShadowClipMode::Inset => 1.0,
};
// If we have a border radius, we'll need to apply
// a clip-out mask.
// Outset box shadows with border radius
// need a clip out of the center box.
let extra_clip_mode = match clip_mode {
BoxShadowClipMode::Outset | BoxShadowClipMode::None => ClipMode::ClipOut,
BoxShadowClipMode::Inset => ClipMode::Clip,
};
let extra_clip = if border_radius > 0.0 {
Some(ClipSource::Complex(*box_bounds,
border_radius,
ClipMode::ClipOut))
extra_clip_mode))
} else {
None
};
@ -1206,7 +1131,7 @@ impl FrameBuilder {
HardwareCompositeOp::PremultipliedAlpha,
next_z);
next_z += 1;
prev_task.as_alpha_batch().alpha_items.push(item);
prev_task.as_alpha_batch().items.push(item);
prev_task.children.push(current_task);
current_task = prev_task;
}
@ -1218,7 +1143,7 @@ impl FrameBuilder {
*filter,
next_z);
next_z += 1;
prev_task.as_alpha_batch().alpha_items.push(item);
prev_task.as_alpha_batch().items.push(item);
prev_task.children.push(current_task);
current_task = prev_task;
}
@ -1234,7 +1159,7 @@ impl FrameBuilder {
mix_blend_mode,
next_z);
next_z += 1;
prev_task.as_alpha_batch().alpha_items.push(item);
prev_task.as_alpha_batch().items.push(item);
prev_task.children.push(current_task);
prev_task.children.push(readback_task);
current_task = prev_task;
@ -1251,10 +1176,9 @@ impl FrameBuilder {
let stacking_context_index = *sc_stack.last().unwrap();
let group_index = self.stacking_context_store[stacking_context_index.0]
.clip_scroll_group(scroll_layer_id);
let xf_rect = match &self.clip_scroll_group_store[group_index.0].xf_rect {
&Some(ref xf_rect) => xf_rect,
&None => continue,
};
if self.clip_scroll_group_store[group_index.0].xf_rect.is_none() {
continue
}
for i in 0..prim_count {
let prim_index = PrimitiveIndex(first_prim_index.0 + i);
@ -1270,17 +1194,8 @@ impl FrameBuilder {
current_task.children.push(clip_task.clone());
}
let needs_clipping = prim_metadata.clip_task.is_some();
let needs_blending = xf_rect.kind == TransformedRectKind::Complex ||
!prim_metadata.is_opaque ||
needs_clipping;
let items = if needs_blending {
&mut current_task.as_alpha_batch().alpha_items
} else {
&mut current_task.as_alpha_batch().opaque_items
};
items.push(AlphaRenderItem::Primitive(group_index, prim_index, next_z));
let item = AlphaRenderItem::Primitive(group_index, prim_index, next_z);
current_task.as_alpha_batch().items.push(item);
next_z += 1;
}
}
@ -1449,12 +1364,12 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
let commands = mem::replace(&mut self.frame_builder.cmds, Vec::new());
for cmd in &commands {
match cmd {
&PrimitiveRunCmd::PushStackingContext(stacking_context_index) =>
match *cmd {
PrimitiveRunCmd::PushStackingContext(stacking_context_index) =>
self.handle_push_stacking_context(stacking_context_index),
&PrimitiveRunCmd::PrimitiveRun(prim_index, prim_count, scroll_layer_id) =>
PrimitiveRunCmd::PrimitiveRun(prim_index, prim_count, scroll_layer_id) =>
self.handle_primitive_run(prim_index, prim_count, scroll_layer_id),
&PrimitiveRunCmd::PopStackingContext => self.handle_pop_stacking_context(),
PrimitiveRunCmd::PopStackingContext => self.handle_pop_stacking_context(),
}
}

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

@ -197,19 +197,19 @@ pub struct PackedTexel {
impl PackedTexel {
pub fn high_bytes(color: &ColorF) -> PackedTexel {
Self::extract_bytes(color, COLOR_FLOAT_TO_FIXED)
Self::extract_bytes(color, 8)
}
pub fn low_bytes(color: &ColorF) -> PackedTexel {
Self::extract_bytes(color, COLOR_FLOAT_TO_FIXED_WIDE)
Self::extract_bytes(color, 0)
}
fn extract_bytes(color: &ColorF, multiplier: f32) -> PackedTexel {
fn extract_bytes(color: &ColorF, shift_by: i32) -> PackedTexel {
PackedTexel {
b: ((0.5 + color.b * multiplier).floor() as u32 & 0xff) as u8,
g: ((0.5 + color.g * multiplier).floor() as u32 & 0xff) as u8,
r: ((0.5 + color.r * multiplier).floor() as u32 & 0xff) as u8,
a: ((0.5 + color.a * multiplier).floor() as u32 & 0xff) as u8,
b: ((0.5 + color.b * COLOR_FLOAT_TO_FIXED_WIDE).floor() as u32 >> shift_by & 0xff) as u8,
g: ((0.5 + color.g * COLOR_FLOAT_TO_FIXED_WIDE).floor() as u32 >> shift_by & 0xff) as u8,
r: ((0.5 + color.r * COLOR_FLOAT_TO_FIXED_WIDE).floor() as u32 >> shift_by & 0xff) as u8,
a: ((0.5 + color.a * COLOR_FLOAT_TO_FIXED_WIDE).floor() as u32 >> shift_by & 0xff) as u8,
}
}
}
@ -392,8 +392,8 @@ pub enum HardwareCompositeOp {
impl HardwareCompositeOp {
pub fn to_blend_mode(&self) -> BlendMode {
match self {
&HardwareCompositeOp::PremultipliedAlpha => BlendMode::PremultipliedAlpha,
match *self {
HardwareCompositeOp::PremultipliedAlpha => BlendMode::PremultipliedAlpha,
}
}
}

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

@ -2,16 +2,16 @@
* 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/. */
//! A GPU based Webrender.
//! A GPU based renderer for the web.
//!
//! It serves as an experimental render backend for [Servo](https://servo.org/),
//! but it can also be used as such in a standalone application.
//!
//! # External dependencies
//! Webrender currently depends on [FreeType](https://www.freetype.org/)
//! WebRender currently depends on [FreeType](https://www.freetype.org/)
//!
//! # Api Structure
//! The main entry point to webrender is the `webrender::renderer::Renderer`.
//! The main entry point to WebRender is the `webrender::renderer::Renderer`.
//!
//! By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
//! Your `Renderer` is responsible to render the previously processed frames onto the screen.
@ -46,6 +46,7 @@ extern crate bitflags;
extern crate thread_profiler;
mod batch_builder;
mod border;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;

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

@ -6,7 +6,7 @@ use gpu_store::GpuStoreAddress;
use prim_store::{ClipData, GpuBlock32, PrimitiveStore};
use prim_store::{CLIP_DATA_GPU_SIZE, MASK_DATA_GPU_SIZE};
use renderer::VertexDataStore;
use util::{MatrixHelpers, TransformedRect};
use util::{ComplexClipRegionHelpers, MatrixHelpers, TransformedRect};
use webrender_traits::{AuxiliaryLists, BorderRadius, ClipRegion, ComplexClipRegion, ImageMask};
use webrender_traits::{DeviceIntRect, LayerToWorldTransform};
use webrender_traits::{LayerRect, LayerPoint, LayerSize};
@ -39,9 +39,9 @@ pub enum ClipSource {
impl ClipSource {
pub fn image_mask(&self) -> Option<ImageMask> {
match self {
&ClipSource::Complex(..) => None,
&ClipSource::Region(ref region, _) => region.image_mask,
match *self {
ClipSource::Complex(..) => None,
ClipSource::Region(ref region, _) => region.image_mask,
}
}
}
@ -73,7 +73,7 @@ impl Geometry {
transform: &LayerToWorldTransform,
device_pixel_ratio: f32) {
let transformed = TransformedRect::new(&self.local_rect,
&transform,
transform,
device_pixel_ratio);
self.bounding_rect = transformed.bounding_rect;
}
@ -123,11 +123,11 @@ impl MaskCacheInfo {
// Work out how much clip data space we need to allocate
// and if we have an image mask.
for clip in clips {
match clip {
&ClipSource::Complex(..) => {
match *clip {
ClipSource::Complex(..) => {
clip_count += 1;
},
&ClipSource::Region(ref region, region_mode) => {
ClipSource::Region(ref region, region_mode) => {
if let Some(info) = region.image_mask {
debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask!
image = Some((info, clip_store.alloc(MASK_DATA_GPU_SIZE)));
@ -179,8 +179,8 @@ impl MaskCacheInfo {
self.is_aligned = is_aligned;
for source in sources {
match source {
&ClipSource::Complex(rect, radius, mode) => {
match *source {
ClipSource::Complex(rect, radius, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
@ -195,9 +195,9 @@ impl MaskCacheInfo {
PrimitiveStore::populate_clip_data(slice, data);
local_rect = local_rect.and_then(|r| r.intersection(&rect));
local_inner = ComplexClipRegion::new(rect, BorderRadius::uniform(radius))
.get_inner_rect();
.get_inner_rect_safe();
}
&ClipSource::Region(ref region, region_mode) => {
ClipSource::Region(ref region, region_mode) => {
local_rect = local_rect.and_then(|r| r.intersection(&region.main));
local_inner = match region.image_mask {
Some(ref mask) if !mask.repeat => {
@ -228,8 +228,8 @@ impl MaskCacheInfo {
let data = ClipData::from_clip_region(clip);
PrimitiveStore::populate_clip_data(chunk, data);
local_rect = local_rect.and_then(|r| r.intersection(&clip.rect));
local_inner = local_inner.and_then(|r| clip.get_inner_rect()
.and_then(|ref inner| r.intersection(&inner)));
local_inner = local_inner.and_then(|r| clip.get_inner_rect_safe()
.and_then(|ref inner| r.intersection(inner)));
}
}
}

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

@ -148,7 +148,7 @@ impl FontContext {
}
pub fn delete_font(&mut self, font_key: &FontKey) {
if let Some(cg_font) = self.cg_fonts.remove(font_key) {
if let Some(_) = self.cg_fonts.remove(font_key) {
// Unstable Rust has a retain() method on HashMap that will
// let us do this in-place. https://github.com/rust-lang/rust/issues/36648
let ct_font_keys = self.ct_fonts.keys()
@ -220,7 +220,7 @@ impl FontContext {
}
#[allow(dead_code)]
fn print_glyph_data(&mut self, data: &Vec<u8>, width: usize, height: usize) {
fn print_glyph_data(&mut self, data: &[u8], width: usize, height: usize) {
// Rust doesn't have step_by support on stable :(
println!("Width is: {:?} height: {:?}", width, height);
for i in 0..height {
@ -376,7 +376,7 @@ impl FontContext {
})
}
None => {
return Some(RasterizedGlyph::blank());
Some(RasterizedGlyph::blank())
}
}
}

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

@ -150,7 +150,7 @@ impl FontContext {
// Assumes RGB format from dwrite, which is 3 bytes per pixel as dwrite
// doesn't output an alpha value via GlyphRunAnalysis::CreateAlphaTexture
#[allow(dead_code)]
fn print_glyph_data(&self, data: &Vec<u8>, width: usize, height: usize) {
fn print_glyph_data(&self, data: &[u8], width: usize, height: usize) {
// Rust doesn't have step_by support on stable :(
for i in 0..height {
let current_height = i * width * 3;
@ -218,7 +218,7 @@ impl FontContext {
// DWRITE gives us values in RGB. WR doesn't really touch it after. Note, CG returns in BGR
// TODO: Decide whether all fonts should return RGB or BGR
fn convert_to_rgba(&self, pixels: &Vec<u8>, render_mode: FontRenderMode) -> Vec<u8> {
fn convert_to_rgba(&self, pixels: &[u8], render_mode: FontRenderMode) -> Vec<u8> {
match render_mode {
FontRenderMode::Mono => {
let mut rgba_pixels: Vec<u8> = vec![0; pixels.len() * 4];

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

@ -128,6 +128,12 @@ pub struct PrimitiveMetadata {
pub clip_task: Option<RenderTask>,
}
impl PrimitiveMetadata {
pub fn needs_clipping(&self) -> bool {
self.clip_task.is_some()
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct RectanglePrimitive {
@ -185,7 +191,6 @@ impl YuvImagePrimitiveGpu {
#[derive(Debug, Clone)]
pub struct BorderPrimitiveCpu {
pub inner_rect: LayerRect,
}
#[derive(Debug, Clone)]
@ -230,8 +235,10 @@ pub struct GradientStopGpu {
pub struct GradientPrimitiveGpu {
pub start_point: LayerPoint,
pub end_point: LayerPoint,
pub tile_size: LayerSize,
pub tile_repeat: LayerSize,
pub extend_mode: f32,
pub padding: [f32; 3],
pub padding: [f32; 7],
}
#[derive(Debug)]
@ -251,6 +258,9 @@ pub struct RadialGradientPrimitiveGpu {
pub end_radius: f32,
pub ratio_xy: f32,
pub extend_mode: f32,
pub tile_size: LayerSize,
pub tile_repeat: LayerSize,
pub padding: [f32; 4],
}
#[derive(Debug)]
@ -718,7 +728,7 @@ impl PrimitiveStore {
metadata
}
PrimitiveContainer::AlignedGradient(gradient_cpu, gradient_gpu) => {
let gpu_address = self.gpu_data32.push(gradient_gpu);
let gpu_address = self.gpu_data64.push(gradient_gpu);
let gpu_stops_address = self.gpu_data32.alloc(gradient_cpu.stops_range.length);
let metadata = PrimitiveMetadata {
@ -739,7 +749,7 @@ impl PrimitiveStore {
metadata
}
PrimitiveContainer::AngleGradient(gradient_cpu, gradient_gpu) => {
let gpu_address = self.gpu_data32.push(gradient_gpu);
let gpu_address = self.gpu_data64.push(gradient_gpu);
let gpu_gradient_address = self.gpu_gradient_data.alloc(1);
let metadata = PrimitiveMetadata {
@ -760,7 +770,7 @@ impl PrimitiveStore {
metadata
}
PrimitiveContainer::RadialGradient(radial_gradient_cpu, radial_gradient_gpu) => {
let gpu_address = self.gpu_data32.push(radial_gradient_gpu);
let gpu_address = self.gpu_data64.push(radial_gradient_gpu);
let gpu_gradient_address = self.gpu_gradient_data.alloc(1);
let metadata = PrimitiveMetadata {
@ -1068,7 +1078,7 @@ impl PrimitiveStore {
device_pixel_ratio,
auxiliary_lists);
for clip in &metadata.clips {
if let &ClipSource::Region(ClipRegion{ image_mask: Some(ref mask), .. }, _) = clip {
if let ClipSource::Region(ClipRegion{ image_mask: Some(ref mask), .. }, _) = *clip {
resource_cache.request_image(mask.image, ImageRendering::Auto, None);
prim_needs_resolve = true;
}
@ -1337,14 +1347,6 @@ impl Default for GpuBlock32 {
}
}
impl From<GradientPrimitiveGpu> for GpuBlock32 {
fn from(data: GradientPrimitiveGpu) -> GpuBlock32 {
unsafe {
mem::transmute::<GradientPrimitiveGpu, GpuBlock32>(data)
}
}
}
impl From<GradientStopGpu> for GpuBlock32 {
fn from(data: GradientStopGpu) -> GpuBlock32 {
unsafe {
@ -1353,14 +1355,6 @@ impl From<GradientStopGpu> for GpuBlock32 {
}
}
impl From<RadialGradientPrimitiveGpu> for GpuBlock32 {
fn from(data: RadialGradientPrimitiveGpu) -> GpuBlock32 {
unsafe {
mem::transmute::<RadialGradientPrimitiveGpu, GpuBlock32>(data)
}
}
}
impl From<YuvImagePrimitiveGpu> for GpuBlock16 {
fn from(data: YuvImagePrimitiveGpu) -> GpuBlock16 {
unsafe {
@ -1407,6 +1401,22 @@ impl Default for GpuBlock64 {
}
}
impl From<GradientPrimitiveGpu> for GpuBlock64 {
fn from(data: GradientPrimitiveGpu) -> GpuBlock64 {
unsafe {
mem::transmute::<GradientPrimitiveGpu, GpuBlock64>(data)
}
}
}
impl From<RadialGradientPrimitiveGpu> for GpuBlock64 {
fn from(data: RadialGradientPrimitiveGpu) -> GpuBlock64 {
unsafe {
mem::transmute::<RadialGradientPrimitiveGpu, GpuBlock64>(data)
}
}
}
impl From<BoxShadowPrimitiveGpu> for GpuBlock64 {
fn from(data: BoxShadowPrimitiveGpu) -> GpuBlock64 {
unsafe {

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

@ -63,19 +63,19 @@ impl ApiRecordingReceiver for BinaryRecorder {
}
pub fn should_record_msg(msg: &ApiMsg) -> bool {
match msg {
&ApiMsg::AddRawFont(..) |
&ApiMsg::AddNativeFont(..) |
&ApiMsg::DeleteFont(..) |
&ApiMsg::AddImage(..) |
&ApiMsg::GenerateFrame(..) |
&ApiMsg::UpdateImage(..) |
&ApiMsg::DeleteImage(..) |
&ApiMsg::SetDisplayList(..) |
&ApiMsg::SetRootPipeline(..) |
&ApiMsg::Scroll(..) |
&ApiMsg::TickScrollingBounce |
&ApiMsg::WebGLCommand(..) =>
match *msg {
ApiMsg::AddRawFont(..) |
ApiMsg::AddNativeFont(..) |
ApiMsg::DeleteFont(..) |
ApiMsg::AddImage(..) |
ApiMsg::GenerateFrame(..) |
ApiMsg::UpdateImage(..) |
ApiMsg::DeleteImage(..) |
ApiMsg::SetDisplayList(..) |
ApiMsg::SetRootPipeline(..) |
ApiMsg::Scroll(..) |
ApiMsg::TickScrollingBounce |
ApiMsg::WebGLCommand(..) =>
true,
_ => false
}

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

@ -301,7 +301,7 @@ impl RenderBackend {
if let Some(ref wrapper) = self.webrender_context_handle {
let dispatcher: Option<Box<GLContextDispatcher>> = if cfg!(target_os = "windows") {
Some(Box::new(WebRenderGLDispatcher {
dispatcher: self.main_thread_dispatcher.clone()
dispatcher: Arc::clone(&self.main_thread_dispatcher)
}))
} else {
None

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

@ -60,8 +60,7 @@ pub enum AlphaRenderItem {
#[derive(Debug, Clone)]
pub struct AlphaRenderTask {
screen_origin: DeviceIntPoint,
pub opaque_items: Vec<AlphaRenderItem>,
pub alpha_items: Vec<AlphaRenderItem>,
pub items: Vec<AlphaRenderItem>,
pub isolate_clear: bool,
}
@ -153,8 +152,7 @@ impl RenderTask {
location: location,
kind: RenderTaskKind::Alpha(AlphaRenderTask {
screen_origin: screen_origin,
alpha_items: Vec::new(),
opaque_items: Vec::new(),
items: Vec::new(),
isolate_clear: isolate_clear,
}),
}
@ -198,14 +196,14 @@ impl RenderTask {
// be optimized later.
let mut result = Some(actual_rect);
for &(_, ref clip) in clips {
match clip.bounds.as_ref().unwrap() {
&MaskBounds::OuterInner(ref outer, _) |
&MaskBounds::Outer(ref outer) => {
match *clip.bounds.as_ref().unwrap() {
MaskBounds::OuterInner(ref outer, _) |
MaskBounds::Outer(ref outer) => {
result = result.and_then(|rect| {
rect.intersection(&outer.bounding_rect)
});
}
&MaskBounds::None => {
MaskBounds::None => {
result = Some(actual_rect);
break;
}
@ -223,10 +221,10 @@ impl RenderTask {
let inner_rect = clips.iter()
.fold(Some(task_rect), |current, clip| {
current.and_then(|rect| {
let inner_rect = match clip.1.bounds.as_ref().unwrap() {
&MaskBounds::Outer(..) |
&MaskBounds::None => DeviceIntRect::zero(),
&MaskBounds::OuterInner(_, ref inner) => inner.bounding_rect
let inner_rect = match *clip.1.bounds.as_ref().unwrap() {
MaskBounds::Outer(..) |
MaskBounds::None => DeviceIntRect::zero(),
MaskBounds::OuterInner(_, ref inner) => inner.bounding_rect
};
rect.intersection(&inner_rect)
})

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

@ -42,7 +42,7 @@ use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use texture_cache::TextureCache;
use threadpool::ThreadPool;
use tiling::{AlphaBatchKind, BlurCommand, Frame, PrimitiveBatch, PrimitiveBatchData, RenderTarget};
use tiling::{AlphaBatchKind, BlurCommand, Frame, PrimitiveBatch, RenderTarget};
use tiling::{AlphaRenderTarget, CacheClipInstance, PrimitiveInstance, ColorRenderTarget, RenderTargetKind};
use time::precise_time_ns;
use thread_profiler::{register_thread_with_profiler, write_profile};
@ -589,7 +589,7 @@ impl Renderer {
let file_watch_handler = FileWatcher {
result_tx: result_tx.clone(),
notifier: notifier.clone(),
notifier: Arc::clone(&notifier),
};
let mut device = Device::new(gl,
@ -857,11 +857,11 @@ impl Renderer {
device.end_frame();
let main_thread_dispatcher = Arc::new(Mutex::new(None));
let backend_notifier = notifier.clone();
let backend_main_thread_dispatcher = main_thread_dispatcher.clone();
let backend_notifier = Arc::clone(&notifier);
let backend_main_thread_dispatcher = Arc::clone(&main_thread_dispatcher);
let vr_compositor = Arc::new(Mutex::new(None));
let backend_vr_compositor = vr_compositor.clone();
let backend_vr_compositor = Arc::clone(&vr_compositor);
// We need a reference to the webrender context from the render backend in order to share
// texture ids
@ -981,7 +981,7 @@ impl Renderer {
*notifier_arc = Some(notifier);
}
/// Sets the new MainThreadDispatcher.
/// Sets the new main thread dispatcher.
///
/// Allows to dispatch functions to the main thread's event loop.
pub fn set_main_thread_dispatcher(&self, dispatcher: Box<RenderDispatcher>) {
@ -1006,7 +1006,7 @@ impl Renderer {
/// Returns a HashMap containing the pipeline ids that have been received by the renderer and
/// their respective epochs since the last time the method was called.
pub fn flush_rendered_epochs(&mut self) -> HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>> {
return mem::replace(&mut self.pipeline_epoch_map, HashMap::with_hasher(Default::default()));
mem::replace(&mut self.pipeline_epoch_map, HashMap::with_hasher(Default::default()))
}
/// Processes the result queue.
@ -1316,7 +1316,7 @@ impl Renderer {
fn submit_batch(&mut self,
batch: &PrimitiveBatch,
projection: &Matrix4D<f32>,
render_task_data: &Vec<RenderTaskData>,
render_task_data: &[RenderTaskData],
cache_texture: TextureId,
render_target: Option<(TextureId, i32)>,
target_dimensions: DeviceUintSize) {
@ -1326,144 +1326,139 @@ impl Renderer {
batch.key.blend_mode == BlendMode::Alpha ||
batch.key.blend_mode == BlendMode::PremultipliedAlpha);
match batch.data {
PrimitiveBatchData::Instances(ref data) => {
let (marker, shader) = match batch.key.kind {
AlphaBatchKind::Composite => unreachable!(),
AlphaBatchKind::HardwareComposite => {
let shader = self.ps_hw_composite.get(&mut self.device);
(GPU_TAG_PRIM_HW_COMPOSITE, shader)
}
AlphaBatchKind::Blend => {
let shader = self.ps_blend.get(&mut self.device);
(GPU_TAG_PRIM_BLEND, shader)
}
AlphaBatchKind::Rectangle => {
let shader = if needs_clipping {
self.ps_rectangle_clip.get(&mut self.device, transform_kind)
} else {
self.ps_rectangle.get(&mut self.device, transform_kind)
};
(GPU_TAG_PRIM_RECT, shader)
}
AlphaBatchKind::TextRun => {
let shader = match batch.key.blend_mode {
BlendMode::Subpixel(..) => self.ps_text_run_subpixel.get(&mut self.device, transform_kind),
BlendMode::Alpha | BlendMode::PremultipliedAlpha | BlendMode::None => self.ps_text_run.get(&mut self.device, transform_kind),
};
(GPU_TAG_PRIM_TEXT_RUN, shader)
}
AlphaBatchKind::Image => {
let shader = self.ps_image.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_IMAGE, shader)
}
AlphaBatchKind::ImageRect => {
let shader = self.ps_image_rect.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_IMAGE_RECT, shader)
}
AlphaBatchKind::YuvImage => {
let shader = self.ps_yuv_image.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_YUV_IMAGE, shader)
}
AlphaBatchKind::Border => {
let shader = self.ps_border.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_BORDER, shader)
}
AlphaBatchKind::AlignedGradient => {
let shader = self.ps_gradient.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_GRADIENT, shader)
}
AlphaBatchKind::AngleGradient => {
let shader = self.ps_angle_gradient.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_ANGLE_GRADIENT, shader)
}
AlphaBatchKind::RadialGradient => {
let shader = self.ps_radial_gradient.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_RADIAL_GRADIENT, shader)
}
AlphaBatchKind::BoxShadow => {
let shader = self.ps_box_shadow.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_BOX_SHADOW, shader)
}
AlphaBatchKind::CacheImage => {
let shader = self.ps_cache_image.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_CACHE_IMAGE, shader)
}
let (marker, shader) = match batch.key.kind {
AlphaBatchKind::Composite => {
let shader = self.ps_composite.get(&mut self.device);
(GPU_TAG_PRIM_COMPOSITE, shader)
}
AlphaBatchKind::HardwareComposite => {
let shader = self.ps_hw_composite.get(&mut self.device);
(GPU_TAG_PRIM_HW_COMPOSITE, shader)
}
AlphaBatchKind::Blend => {
let shader = self.ps_blend.get(&mut self.device);
(GPU_TAG_PRIM_BLEND, shader)
}
AlphaBatchKind::Rectangle => {
let shader = if needs_clipping {
self.ps_rectangle_clip.get(&mut self.device, transform_kind)
} else {
self.ps_rectangle.get(&mut self.device, transform_kind)
};
let shader = shader.unwrap();
let _gm = self.gpu_profile.add_marker(marker);
let vao = self.prim_vao_id;
self.draw_instanced_batch(data,
vao,
shader,
&batch.key.textures,
projection);
(GPU_TAG_PRIM_RECT, shader)
}
PrimitiveBatchData::Composite(ref instance) => {
let _gm = self.gpu_profile.add_marker(GPU_TAG_PRIM_COMPOSITE);
let vao = self.prim_vao_id;
let shader = self.ps_composite.get(&mut self.device).unwrap();
// TODO(gw): This code branch is all a bit hacky. We rely
// on pulling specific values from the render target data
// and also cloning the single primitive instance to be
// able to pass to draw_instanced_batch(). We should
// think about a cleaner way to achieve this!
// Before submitting the composite batch, do the
// framebuffer readbacks that are needed for each
// composite operation in this batch.
let cache_texture_dimensions = self.device.get_texture_dimensions(cache_texture);
let backdrop = &render_task_data[instance.task_index as usize];
let readback = &render_task_data[instance.user_data[0] as usize];
let source = &render_task_data[instance.user_data[1] as usize];
// Bind the FBO to blit the backdrop to.
// Called per-instance in case the layer (and therefore FBO)
// changes. The device will skip the GL call if the requested
// target is already bound.
let cache_draw_target = (cache_texture, readback.data[4] as i32);
self.device.bind_draw_target(Some(cache_draw_target), Some(cache_texture_dimensions));
let src_x = backdrop.data[0] - backdrop.data[4] + source.data[4];
let src_y = backdrop.data[1] - backdrop.data[5] + source.data[5];
let dest_x = readback.data[0];
let dest_y = readback.data[1];
let width = readback.data[2];
let height = readback.data[3];
let mut src = DeviceIntRect::new(DeviceIntPoint::new(src_x as i32, src_y as i32),
DeviceIntSize::new(width as i32, height as i32));
let mut dest = DeviceIntRect::new(DeviceIntPoint::new(dest_x as i32, dest_y as i32),
DeviceIntSize::new(width as i32, height as i32));
// Need to invert the y coordinates and flip the image vertically when
// reading back from the framebuffer.
if render_target.is_none() {
src.origin.y = target_dimensions.height as i32 - src.size.height - src.origin.y;
dest.origin.y += dest.size.height;
dest.size.height = -dest.size.height;
}
self.device.blit_render_target(render_target,
Some(src),
dest);
// Restore draw target to current pass render target + layer.
self.device.bind_draw_target(render_target, Some(target_dimensions));
self.draw_instanced_batch(&[instance.clone()],
vao,
shader,
&batch.key.textures,
projection);
AlphaBatchKind::TextRun => {
let shader = match batch.key.blend_mode {
BlendMode::Subpixel(..) => self.ps_text_run_subpixel.get(&mut self.device, transform_kind),
BlendMode::Alpha | BlendMode::PremultipliedAlpha | BlendMode::None => self.ps_text_run.get(&mut self.device, transform_kind),
};
(GPU_TAG_PRIM_TEXT_RUN, shader)
}
AlphaBatchKind::Image => {
let shader = self.ps_image.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_IMAGE, shader)
}
AlphaBatchKind::ImageRect => {
let shader = self.ps_image_rect.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_IMAGE_RECT, shader)
}
AlphaBatchKind::YuvImage => {
let shader = self.ps_yuv_image.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_YUV_IMAGE, shader)
}
AlphaBatchKind::Border => {
let shader = self.ps_border.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_BORDER, shader)
}
AlphaBatchKind::AlignedGradient => {
let shader = self.ps_gradient.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_GRADIENT, shader)
}
AlphaBatchKind::AngleGradient => {
let shader = self.ps_angle_gradient.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_ANGLE_GRADIENT, shader)
}
AlphaBatchKind::RadialGradient => {
let shader = self.ps_radial_gradient.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_RADIAL_GRADIENT, shader)
}
AlphaBatchKind::BoxShadow => {
let shader = self.ps_box_shadow.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_BOX_SHADOW, shader)
}
AlphaBatchKind::CacheImage => {
let shader = self.ps_cache_image.get(&mut self.device, transform_kind);
(GPU_TAG_PRIM_CACHE_IMAGE, shader)
}
};
// Handle special case readback for composites.
if batch.key.kind == AlphaBatchKind::Composite {
// composites can't be grouped together because
// they may overlap and affect each other.
debug_assert!(batch.instances.len() == 1);
let instance = &batch.instances[0];
// TODO(gw): This code branch is all a bit hacky. We rely
// on pulling specific values from the render target data
// and also cloning the single primitive instance to be
// able to pass to draw_instanced_batch(). We should
// think about a cleaner way to achieve this!
// Before submitting the composite batch, do the
// framebuffer readbacks that are needed for each
// composite operation in this batch.
let cache_texture_dimensions = self.device.get_texture_dimensions(cache_texture);
let backdrop = &render_task_data[instance.task_index as usize];
let readback = &render_task_data[instance.user_data[0] as usize];
let source = &render_task_data[instance.user_data[1] as usize];
// Bind the FBO to blit the backdrop to.
// Called per-instance in case the layer (and therefore FBO)
// changes. The device will skip the GL call if the requested
// target is already bound.
let cache_draw_target = (cache_texture, readback.data[4] as i32);
self.device.bind_draw_target(Some(cache_draw_target), Some(cache_texture_dimensions));
let src_x = backdrop.data[0] - backdrop.data[4] + source.data[4];
let src_y = backdrop.data[1] - backdrop.data[5] + source.data[5];
let dest_x = readback.data[0];
let dest_y = readback.data[1];
let width = readback.data[2];
let height = readback.data[3];
let mut src = DeviceIntRect::new(DeviceIntPoint::new(src_x as i32, src_y as i32),
DeviceIntSize::new(width as i32, height as i32));
let mut dest = DeviceIntRect::new(DeviceIntPoint::new(dest_x as i32, dest_y as i32),
DeviceIntSize::new(width as i32, height as i32));
// Need to invert the y coordinates and flip the image vertically when
// reading back from the framebuffer.
if render_target.is_none() {
src.origin.y = target_dimensions.height as i32 - src.size.height - src.origin.y;
dest.origin.y += dest.size.height;
dest.size.height = -dest.size.height;
}
self.device.blit_render_target(render_target,
Some(src),
dest);
// Restore draw target to current pass render target + layer.
self.device.bind_draw_target(render_target, Some(target_dimensions));
}
let shader = shader.unwrap();
let _gm = self.gpu_profile.add_marker(marker);
let vao = self.prim_vao_id;
self.draw_instanced_batch(&batch.instances,
vao,
shader,
&batch.key.textures,
projection);
}
fn draw_color_target(&mut self,
@ -1472,7 +1467,7 @@ impl Renderer {
target_size: DeviceUintSize,
color_cache_texture: TextureId,
clear_color: Option<[f32; 4]>,
render_task_data: &Vec<RenderTaskData>,
render_task_data: &[RenderTaskData],
projection: &Matrix4D<f32>) {
{
let _gm = self.gpu_profile.add_marker(GPU_TAG_SETUP_TARGET);
@ -1574,7 +1569,7 @@ impl Renderer {
self.device.enable_depth();
self.device.enable_depth_write();
for batch in &target.alpha_batcher.opaque_batches {
for batch in &target.alpha_batcher.batch_list.opaque_batches {
self.submit_batch(batch,
&projection,
render_task_data,
@ -1585,7 +1580,7 @@ impl Renderer {
self.device.disable_depth_write();
for batch in &target.alpha_batcher.alpha_batches {
for batch in &target.alpha_batcher.batch_list.alpha_batches {
if batch.key.blend_mode != prev_blend_mode {
match batch.key.blend_mode {
BlendMode::None => {

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

@ -260,15 +260,14 @@ impl ResourceCache {
fn should_tile(&self, descriptor: &ImageDescriptor, data: &ImageData) -> bool {
let limit = self.max_texture_size();
let size_check = descriptor.width > limit || descriptor.height > limit;
return match data {
&ImageData::Raw(_) => { size_check }
&ImageData::Blob(_) => { size_check }
&ImageData::External(info) => {
match *data {
ImageData::Raw(_) | ImageData::Blob(_) => { size_check }
ImageData::External(info) => {
// External handles already represent existing textures so it does
// not make sense to tile them into smaller ones.
info.image_type == ExternalImageType::ExternalBuffer && size_check
},
};
}
}
pub fn add_font_template(&mut self, font_key: FontKey, template: FontTemplate) {
@ -315,9 +314,9 @@ impl ResourceCache {
data: ImageData,
dirty_rect: Option<DeviceUintRect>) {
let resource = if let Some(image) = self.image_templates.get(&image_key) {
assert!(image.descriptor.width == descriptor.width);
assert!(image.descriptor.height == descriptor.height);
assert!(image.descriptor.format == descriptor.format);
assert_eq!(image.descriptor.width, descriptor.width);
assert_eq!(image.descriptor.height, descriptor.height);
assert_eq!(image.descriptor.format, descriptor.format);
let next_epoch = Epoch(image.epoch.0 + 1);
@ -349,17 +348,14 @@ impl ResourceCache {
// If the key is associated to an external image, pass the external id to renderer for cleanup.
if let Some(image) = value {
match image.data {
ImageData::External(ext_image) => {
match ext_image.image_type {
ExternalImageType::Texture2DHandle |
ExternalImageType::TextureRectHandle => {
self.pending_external_image_update_list.push(ext_image.id);
}
_ => {}
if let ImageData::External(ext_image) = image.data {
match ext_image.image_type {
ExternalImageType::Texture2DHandle |
ExternalImageType::TextureRectHandle => {
self.pending_external_image_update_list.push(ext_image.id);
}
_ => {}
}
_ => {}
}
return;
@ -406,7 +402,7 @@ impl ResourceCache {
if !same_epoch && self.blob_image_requests.insert(request) {
renderer.request_blob_image(
key,
data.clone(),
Arc::clone(data),
&BlobImageDescriptor {
width: template.descriptor.width,
height: template.descriptor.height,
@ -846,7 +842,7 @@ fn spawn_glyph_cache_thread(workers: Arc<Mutex<ThreadPool>>) -> (Sender<GlyphCac
let barrier = Arc::new(Barrier::new(worker_count));
for i in 0..worker_count {
let barrier = barrier.clone();
let barrier = Arc::clone(&barrier);
workers.lock().unwrap().execute(move || {
register_thread_with_profiler(format!("Glyph Worker {}", i));
barrier.wait();
@ -882,7 +878,7 @@ fn spawn_glyph_cache_thread(workers: Arc<Mutex<ThreadPool>>) -> (Sender<GlyphCac
// added to each worker thread.
let barrier = Arc::new(Barrier::new(worker_count));
for _ in 0..worker_count {
let barrier = barrier.clone();
let barrier = Arc::clone(&barrier);
let font_template = font_template.clone();
workers.lock().unwrap().execute(move || {
FONT_CONTEXT.with(|font_context| {
@ -908,7 +904,7 @@ fn spawn_glyph_cache_thread(workers: Arc<Mutex<ThreadPool>>) -> (Sender<GlyphCac
// Delete a font from the font context in each worker thread.
let barrier = Arc::new(Barrier::new(worker_count));
for _ in 0..worker_count {
let barrier = barrier.clone();
let barrier = Arc::clone(&barrier);
workers.lock().unwrap().execute(move || {
FONT_CONTEXT.with(|font_context| {
let mut font_context = font_context.borrow_mut();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -2,10 +2,12 @@
* 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 std::f32::consts::{FRAC_1_SQRT_2};
use euclid::{Point2D, Rect, Size2D};
use euclid::{TypedRect, TypedPoint2D, TypedSize2D, TypedPoint4D, TypedMatrix4D};
use webrender_traits::{DeviceIntRect, DeviceIntPoint, DeviceIntSize};
use webrender_traits::{LayerRect, WorldPoint4D, LayerPoint4D, LayerToWorldTransform};
use webrender_traits::{BorderRadius, ComplexClipRegion, LayoutRect};
use num_traits::Zero;
// TODO: Implement these in euclid!
@ -269,3 +271,50 @@ impl TransformedRect {
pub fn pack_as_float(value: u32) -> f32 {
value as f32 + 0.5
}
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`
extract_inner_rect_impl(&self.rect, &self.radii, k)
}
}
#[inline]
fn extract_inner_rect_impl<U>(rect: &TypedRect<f32, U>,
radii: &BorderRadius,
k: f32) -> Option<TypedRect<f32, U>> {
// `k` defines how much border is taken into account
let xl = rect.origin.x +
k * radii.top_left.width.max(radii.bottom_left.width);
let xr = rect.origin.x + rect.size.width -
k * radii.top_right.width.max(radii.bottom_right.width);
let yt = rect.origin.y +
k * radii.top_left.height.max(radii.top_right.height);
let yb = rect.origin.y + rect.size.height -
k * radii.bottom_left.height.max(radii.bottom_right.height);
if xl <= xr && yt <= yb {
Some(TypedRect::new(TypedPoint2D::new(xl, yt),
TypedSize2D::new(xr-xl, yb-yt)))
} else {
None
}
}

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

@ -5,12 +5,12 @@ authors = ["The Mozilla Project Developers"]
license = "MPL-2.0"
[dependencies]
webrender_traits = {path = "../webrender_traits", version = "0.31.0"}
webrender_traits = {path = "../webrender_traits", version = "0.32.0"}
euclid = "0.11"
app_units = "0.4"
gleam = "0.4"
[dependencies.webrender]
path = "../webrender"
version = "0.30.0"
version = "0.31.0"
default-features = false

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

@ -1060,6 +1060,7 @@ pub extern "C" fn wr_dp_begin(state: &mut WrState, width: u32, height: u32) {
bounds,
0,
None,
TransformStyle::Flat,
None,
MixBlendMode::Normal,
Vec::new());
@ -1131,10 +1132,13 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
bounds,
state.z_index,
Some(PropertyBinding::Value(transform.to_layout_transform())),
TransformStyle::Flat,
None,
mix_blend_mode,
filters);
state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, None);
let clip_bounds = LayoutRect::new(LayoutPoint::new(0.0, 0.0), bounds.size);
state.frame_builder.dl_builder.push_scroll_layer(clip_region, clip_bounds, None);
}
#[no_mangle]
@ -1160,7 +1164,7 @@ pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
}
});
let clip_region = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], mask);
state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, None);
state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds, None);
}
#[no_mangle]
@ -1356,9 +1360,13 @@ pub extern "C" fn wr_dp_push_linear_gradient(state: &mut WrState,
end_point.to_point(),
stops,
extend_mode.to_gradient_extend_mode());
state.frame_builder.dl_builder.push_gradient(rect.to_rect(),
let rect = rect.to_rect();
let tile_size = rect.size.clone();
state.frame_builder.dl_builder.push_gradient(rect,
clip.to_clip_region(),
gradient);
gradient,
tile_size,
LayoutSize::new(0.0, 0.0));
}
#[no_mangle]
@ -1379,9 +1387,13 @@ pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
radius.to_size(),
stops,
extend_mode.to_gradient_extend_mode());
state.frame_builder.dl_builder.push_radial_gradient(rect.to_rect(),
let rect = rect.to_rect();
let tile_size = rect.size.clone();
state.frame_builder.dl_builder.push_radial_gradient(rect,
clip.to_clip_region(),
gradient);
gradient,
tile_size,
LayoutSize::new(0.0, 0.0));
}
#[no_mangle]

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

@ -1,6 +1,6 @@
[package]
name = "webrender_traits"
version = "0.31.0"
version = "0.32.0"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"

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

@ -67,34 +67,34 @@ pub enum ApiMsg {
impl fmt::Debug for ApiMsg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ApiMsg::AddRawFont(..) => { write!(f, "ApiMsg::AddRawFont") }
&ApiMsg::AddNativeFont(..) => { write!(f, "ApiMsg::AddNativeFont") }
&ApiMsg::DeleteFont(..) => { write!(f, "ApiMsg::DeleteFont") }
&ApiMsg::GetGlyphDimensions(..) => { write!(f, "ApiMsg::GetGlyphDimensions") }
&ApiMsg::AddImage(..) => { write!(f, "ApiMsg::AddImage") }
&ApiMsg::UpdateImage(..) => { write!(f, "ApiMsg::UpdateImage") }
&ApiMsg::DeleteImage(..) => { write!(f, "ApiMsg::DeleteImage") }
&ApiMsg::CloneApi(..) => { write!(f, "ApiMsg::CloneApi") }
&ApiMsg::SetDisplayList(..) => { write!(f, "ApiMsg::SetDisplayList") }
&ApiMsg::SetRootPipeline(..) => { write!(f, "ApiMsg::SetRootPipeline") }
&ApiMsg::Scroll(..) => { write!(f, "ApiMsg::Scroll") }
&ApiMsg::ScrollLayerWithId(..) => { write!(f, "ApiMsg::ScrollLayerWithId") }
&ApiMsg::TickScrollingBounce => { write!(f, "ApiMsg::TickScrollingBounce") }
&ApiMsg::TranslatePointToLayerSpace(..) => { write!(f, "ApiMsg::TranslatePointToLayerSpace") }
&ApiMsg::GetScrollLayerState(..) => { write!(f, "ApiMsg::GetScrollLayerState") }
&ApiMsg::RequestWebGLContext(..) => { write!(f, "ApiMsg::RequestWebGLContext") }
&ApiMsg::ResizeWebGLContext(..) => { write!(f, "ApiMsg::ResizeWebGLContext") }
&ApiMsg::WebGLCommand(..) => { write!(f, "ApiMsg::WebGLCommand") }
&ApiMsg::GenerateFrame(..) => { write!(f, "ApiMsg::GenerateFrame") }
&ApiMsg::VRCompositorCommand(..) => { write!(f, "ApiMsg::VRCompositorCommand") }
&ApiMsg::ExternalEvent(..) => { write!(f, "ApiMsg::ExternalEvent") }
&ApiMsg::ShutDown => { write!(f, "ApiMsg::ShutDown") }
&ApiMsg::SetPageZoom(..) => { write!(f, "ApiMsg::SetPageZoom") }
&ApiMsg::SetPinchZoom(..) => { write!(f, "ApiMsg::SetPinchZoom") }
&ApiMsg::SetPan(..) => { write!(f, "ApiMsg::SetPan") }
&ApiMsg::SetWindowParameters(..) => { write!(f, "ApiMsg::SetWindowParameters") }
}
f.write_str(match *self {
ApiMsg::AddRawFont(..) => "ApiMsg::AddRawFont",
ApiMsg::AddNativeFont(..) => "ApiMsg::AddNativeFont",
ApiMsg::DeleteFont(..) => "ApiMsg::DeleteFont",
ApiMsg::GetGlyphDimensions(..) => "ApiMsg::GetGlyphDimensions",
ApiMsg::AddImage(..) => "ApiMsg::AddImage",
ApiMsg::UpdateImage(..) => "ApiMsg::UpdateImage",
ApiMsg::DeleteImage(..) => "ApiMsg::DeleteImage",
ApiMsg::CloneApi(..) => "ApiMsg::CloneApi",
ApiMsg::SetDisplayList(..) => "ApiMsg::SetDisplayList",
ApiMsg::SetRootPipeline(..) => "ApiMsg::SetRootPipeline",
ApiMsg::Scroll(..) => "ApiMsg::Scroll",
ApiMsg::ScrollLayerWithId(..) => "ApiMsg::ScrollLayerWithId",
ApiMsg::TickScrollingBounce => "ApiMsg::TickScrollingBounce",
ApiMsg::TranslatePointToLayerSpace(..) => "ApiMsg::TranslatePointToLayerSpace",
ApiMsg::GetScrollLayerState(..) => "ApiMsg::GetScrollLayerState",
ApiMsg::RequestWebGLContext(..) => "ApiMsg::RequestWebGLContext",
ApiMsg::ResizeWebGLContext(..) => "ApiMsg::ResizeWebGLContext",
ApiMsg::WebGLCommand(..) => "ApiMsg::WebGLCommand",
ApiMsg::GenerateFrame(..) => "ApiMsg::GenerateFrame",
ApiMsg::VRCompositorCommand(..) => "ApiMsg::VRCompositorCommand",
ApiMsg::ExternalEvent(..) => "ApiMsg::ExternalEvent",
ApiMsg::ShutDown => "ApiMsg::ShutDown",
ApiMsg::SetPageZoom(..) => "ApiMsg::SetPageZoom",
ApiMsg::SetPinchZoom(..) => "ApiMsg::SetPinchZoom",
ApiMsg::SetPan(..) => "ApiMsg::SetPan",
ApiMsg::SetWindowParameters(..) => "ApiMsg::SetWindowParameters",
})
}
}
@ -265,12 +265,14 @@ impl RenderApi {
///
/// # Examples
///
/// ```ignore
/// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
/// ```
/// # use webrender_traits::{PipelineId, RenderApiSender};
/// # fn example(sender: RenderApiSender) {
/// let api = sender.create_api();
/// ...
/// let pipeline_id = PipelineId(0,0);
/// // ...
/// let pipeline_id = PipelineId(0, 0);
/// api.set_root_pipeline(pipeline_id);
/// # }
/// ```
pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
let msg = ApiMsg::SetRootPipeline(pipeline_id);
@ -289,8 +291,8 @@ impl RenderApi {
///
/// * `background_color`: The background color of this pipeline.
/// * `epoch`: The unique Frame ID, monotonically increasing.
/// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
/// * `viewport_size`: The size of the viewport for this frame.
/// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
/// * `display_list`: The root Display list used in this frame.
/// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
/// * `preserve_frame_state`: If a previous frame exists which matches this pipeline
@ -325,7 +327,7 @@ impl RenderApi {
/// Scrolls the scrolling layer under the `cursor`
///
/// Webrender looks for the layer closest to the user
/// WebRender looks for the layer closest to the user
/// which has `ScrollPolicy::Scrollable` set.
pub fn scroll(&self, scroll_location: ScrollLocation, cursor: WorldPoint, phase: ScrollEventPhase) {
let msg = ApiMsg::Scroll(scroll_location, cursor, phase);
@ -557,7 +559,7 @@ pub struct PropertyValue<T> {
pub value: T,
}
/// When using generate_frame(), a list of PropertyValue structures
/// When using `generate_frame()`, a list of `PropertyValue` structures
/// can optionally be supplied to provide the current value of any
/// animated properties.
#[derive(Clone, Deserialize, Serialize, Debug)]
@ -590,7 +592,7 @@ pub trait RenderNotifier: Send {
fn shut_down(&mut self) {}
}
// Trait to allow dispatching functions to a specific thread or event loop.
/// Trait to allow dispatching functions to a specific thread or event loop.
pub trait RenderDispatcher: Send {
fn dispatch(&self, Box<Fn() + Send>);
}

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

@ -69,8 +69,8 @@ impl Payload {
}
/// A helper to handle the interface difference between IpcBytesSender and
/// Sender<Vec<u8>>.
/// A helper to handle the interface difference between `IpcBytesSender`
/// and `Sender<Vec<u8>>`.
pub trait PayloadSenderHelperMethods {
fn send_payload(&self, data: Payload) -> Result<(), Error>;
}

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

@ -43,7 +43,6 @@ pub struct ItemRange {
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ClipDisplayItem {
pub content_size: LayoutSize,
pub id: ScrollLayerId,
pub parent_id: ScrollLayerId,
}
@ -211,6 +210,8 @@ pub struct Gradient {
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct GradientDisplayItem {
pub gradient: Gradient,
pub tile_size: LayoutSize,
pub tile_spacing: LayoutSize,
}
#[repr(C)]
@ -235,6 +236,8 @@ pub struct RadialGradient {
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RadialGradientDisplayItem {
pub gradient: RadialGradient,
pub tile_size: LayoutSize,
pub tile_spacing: LayoutSize,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
@ -247,6 +250,7 @@ pub struct StackingContext {
pub scroll_policy: ScrollPolicy,
pub z_index: i32,
pub transform: Option<PropertyBinding<LayoutTransform>>,
pub transform_style: TransformStyle,
pub perspective: Option<LayoutTransform>,
pub mix_blend_mode: MixBlendMode,
pub filters: ItemRange,
@ -261,6 +265,13 @@ pub enum ScrollPolicy {
known_heap_size!(0, ScrollPolicy);
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TransformStyle {
Flat,
Preserve3D,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum MixBlendMode {
@ -358,6 +369,7 @@ impl StackingContext {
pub fn new(scroll_policy: ScrollPolicy,
z_index: i32,
transform: Option<PropertyBinding<LayoutTransform>>,
transform_style: TransformStyle,
perspective: Option<LayoutTransform>,
mix_blend_mode: MixBlendMode,
filters: Vec<FilterOp>,
@ -367,6 +379,7 @@ impl StackingContext {
scroll_policy: scroll_policy,
z_index: z_index,
transform: transform,
transform_style: transform_style,
perspective: perspective,
mix_blend_mode: mix_blend_mode,
filters: auxiliary_lists_builder.add_filters(&filters),
@ -487,24 +500,6 @@ impl ComplexClipRegion {
radii: radii,
}
}
//TODO: move to `util` module?
/// Return an aligned rectangle that is fully inside the clip region.
pub fn get_inner_rect(&self) -> Option<LayoutRect> {
let xl = self.rect.origin.x +
self.radii.top_left.width.max(self.radii.bottom_left.width);
let xr = self.rect.origin.x + self.rect.size.width -
self.radii.top_right.width.max(self.radii.bottom_right.width);
let yt = self.rect.origin.y +
self.radii.top_left.height.max(self.radii.top_right.height);
let yb = self.rect.origin.y + self.rect.size.height -
self.radii.bottom_left.height.max(self.radii.bottom_right.height);
if xl <= xr && yt <= yb {
Some(LayoutRect::new(LayoutPoint::new(xl, yt), LayoutSize::new(xr-xl, yb-yt)))
} else {
None
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
@ -529,8 +524,8 @@ impl ScrollLayerId {
pub fn pipeline_id(&self) -> PipelineId {
match *self {
ScrollLayerId::Clip(_, pipeline_id) => pipeline_id,
ScrollLayerId::ClipExternalId(_, pipeline_id) => pipeline_id,
ScrollLayerId::Clip(_, pipeline_id) |
ScrollLayerId::ClipExternalId(_, pipeline_id) |
ScrollLayerId::ReferenceFrame(_, pipeline_id) => pipeline_id,
}
}

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

@ -9,11 +9,11 @@ use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShado
use {ClipDisplayItem, ClipRegion, ColorF, ComplexClipRegion, DisplayItem, ExtendMode, FilterOp};
use {FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem, GradientStop};
use {IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering, ItemRange};
use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, MixBlendMode, PipelineId};
use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
use {TransformStyle, MixBlendMode, PipelineId};
use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
use {RectangleDisplayItem, ScrollLayerId, ScrollPolicy, SpecificDisplayItem, StackingContext};
use {TextDisplayItem, WebGLContextId, WebGLDisplayItem, YuvColorSpace};
use YuvImageDisplayItem;
use {TextDisplayItem, WebGLContextId, WebGLDisplayItem, YuvColorSpace, YuvImageDisplayItem};
#[derive(Clone, Deserialize, Serialize)]
pub struct AuxiliaryLists {
@ -80,7 +80,7 @@ impl BuiltDisplayList {
&self.descriptor
}
pub fn all_display_items<'a>(&'a self) -> &'a [DisplayItem] {
pub fn all_display_items(&self) -> &[DisplayItem] {
unsafe {
convert_blob_to_pod(&self.data[0..self.descriptor.display_list_items_size])
}
@ -395,9 +395,13 @@ impl DisplayListBuilder {
pub fn push_gradient(&mut self,
rect: LayoutRect,
clip: ClipRegion,
gradient: Gradient) {
gradient: Gradient,
tile_size: LayoutSize,
tile_spacing: LayoutSize) {
let item = SpecificDisplayItem::Gradient(GradientDisplayItem {
gradient: gradient,
tile_size: tile_size,
tile_spacing: tile_spacing,
});
self.push_item(item, rect, clip);
@ -406,9 +410,13 @@ impl DisplayListBuilder {
pub fn push_radial_gradient(&mut self,
rect: LayoutRect,
clip: ClipRegion,
gradient: RadialGradient) {
gradient: RadialGradient,
tile_size: LayoutSize,
tile_spacing: LayoutSize) {
let item = SpecificDisplayItem::RadialGradient(RadialGradientDisplayItem {
gradient: gradient,
tile_size: tile_size,
tile_spacing: tile_spacing,
});
self.push_item(item, rect, clip);
@ -419,6 +427,7 @@ impl DisplayListBuilder {
bounds: LayoutRect,
z_index: i32,
transform: Option<PropertyBinding<LayoutTransform>>,
transform_style: TransformStyle,
perspective: Option<LayoutTransform>,
mix_blend_mode: MixBlendMode,
filters: Vec<FilterOp>) {
@ -427,6 +436,7 @@ impl DisplayListBuilder {
scroll_policy: scroll_policy,
z_index: z_index,
transform: transform,
transform_style: transform_style,
perspective: perspective,
mix_blend_mode: mix_blend_mode,
filters: self.auxiliary_lists_builder.add_filters(&filters),
@ -441,8 +451,8 @@ impl DisplayListBuilder {
}
pub fn define_clip(&mut self,
content_rect: LayoutRect,
clip: ClipRegion,
content_size: LayoutSize,
id: Option<ScrollLayerId>)
-> ScrollLayerId {
let id = match id {
@ -454,20 +464,19 @@ impl DisplayListBuilder {
};
let item = SpecificDisplayItem::Clip(ClipDisplayItem {
content_size: content_size,
id: id,
parent_id: *self.clip_stack.last().unwrap(),
});
self.push_item(item, clip.main, clip);
self.push_item(item, content_rect, clip);
id
}
pub fn push_scroll_layer(&mut self,
clip: ClipRegion,
content_size: LayoutSize,
content_rect: LayoutRect,
id: Option<ScrollLayerId>) {
let id = self.define_clip(clip, content_size, id);
let id = self.define_clip(content_rect, clip, id);
self.clip_stack.push(id);
}
@ -575,7 +584,7 @@ impl ItemRange {
}
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct AuxiliaryListsBuilder {
gradient_stops: Vec<GradientStop>,
complex_clip_regions: Vec<ComplexClipRegion>,
@ -585,12 +594,7 @@ pub struct AuxiliaryListsBuilder {
impl AuxiliaryListsBuilder {
pub fn new() -> AuxiliaryListsBuilder {
AuxiliaryListsBuilder {
gradient_stops: Vec::new(),
complex_clip_regions: Vec::new(),
filters: Vec::new(),
glyph_instances: Vec::new(),
}
AuxiliaryListsBuilder::default()
}
pub fn add_gradient_stops(&mut self, gradient_stops: &[GradientStop]) -> ItemRange {

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

@ -47,6 +47,14 @@ pub enum FontRenderMode {
Subpixel,
}
const FIXED16_SHIFT: i32 = 16;
// This matches the behaviour of SkScalarToFixed
fn f32_truncate_to_fixed16(x: f32) -> i32 {
let fixed1 = (1 << FIXED16_SHIFT) as f32;
(x * fixed1) as i32
}
impl FontRenderMode {
// Skia quantizes subpixel offets into 1/4 increments.
// Given the absolute position, return the quantized increment
@ -55,14 +63,18 @@ impl FontRenderMode {
return SubpixelOffset::Zero;
}
const SUBPIXEL_ROUNDING :f32 = 0.125; // Skia chosen value.
let fraction = (pos + SUBPIXEL_ROUNDING).fract();
const SUBPIXEL_BITS: i32 = 2;
const SUBPIXEL_FIXED16_MASK: i32 = ((1 << SUBPIXEL_BITS) - 1) << (FIXED16_SHIFT - SUBPIXEL_BITS);
const SUBPIXEL_ROUNDING: f32 = 0.5 / (1 << SUBPIXEL_BITS) as f32;
let pos = pos + SUBPIXEL_ROUNDING;
let fraction = (f32_truncate_to_fixed16(pos) & SUBPIXEL_FIXED16_MASK) >> (FIXED16_SHIFT - SUBPIXEL_BITS);
match fraction {
0.0...0.25 => SubpixelOffset::Zero,
0.25...0.5 => SubpixelOffset::Quarter,
0.5...0.75 => SubpixelOffset::Half,
0.75...1.0 => SubpixelOffset::ThreeQuarters,
0 => SubpixelOffset::Zero,
1 => SubpixelOffset::Quarter,
2 => SubpixelOffset::Half,
3 => SubpixelOffset::ThreeQuarters,
_ => panic!("Should only be given the fractional part"),
}
}
@ -104,7 +116,7 @@ impl SubpixelPoint {
}
pub fn to_f64(&self) -> (f64, f64) {
return (self.x.into(), self.y.into());
(self.x.into(), self.y.into())
}
pub fn set_offset(&mut self, point: Point2D<f32>, render_mode: FontRenderMode) {

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

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![cfg_attr(feature = "nightly", feature(nonzero))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, float_cmp))]
extern crate app_units;
extern crate byteorder;

10
toolkit/library/gtest/rust/Cargo.lock сгенерированный
Просмотреть файл

@ -964,7 +964,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.30.0"
version = "0.31.0"
dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -985,7 +985,7 @@ dependencies = [
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.31.0",
"webrender_traits 0.32.0",
]
[[package]]
@ -995,13 +995,13 @@ dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.30.0",
"webrender_traits 0.31.0",
"webrender 0.31.0",
"webrender_traits 0.32.0",
]
[[package]]
name = "webrender_traits"
version = "0.31.0"
version = "0.32.0"
dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",

10
toolkit/library/rust/Cargo.lock сгенерированный
Просмотреть файл

@ -951,7 +951,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.30.0"
version = "0.31.0"
dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -972,7 +972,7 @@ dependencies = [
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.31.0",
"webrender_traits 0.32.0",
]
[[package]]
@ -982,13 +982,13 @@ dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.30.0",
"webrender_traits 0.31.0",
"webrender 0.31.0",
"webrender_traits 0.32.0",
]
[[package]]
name = "webrender_traits"
version = "0.31.0"
version = "0.32.0"
dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",