зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2df2e6a3af
Коммит
59dd9e78bc
|
@ -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))
|
||||
|
|
@ -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(®ion.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(¬ifier),
|
||||
};
|
||||
|
||||
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(¬ifier);
|
||||
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;
|
||||
|
|
|
@ -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)",
|
||||
|
|
|
@ -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)",
|
||||
|
|
Загрузка…
Ссылка в новой задаче