зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1479432 - Update webrender to commit 7a1b919e37d6cd0155077aa90f98cfcdf9fa5bae. r=jrmuizel
MozReview-Commit-ID: 1SJgRWEp2qf --HG-- extra : rebase_source : ec6ffe0686f8ef0bf8149347fcfd48e3870bc316
This commit is contained in:
Родитель
cad8bf3a7e
Коммит
83d156a753
|
@ -18,20 +18,20 @@ pathfinder = ["pathfinder_font_renderer", "pathfinder_gfx_utils", "pathfinder_pa
|
|||
serialize_program = ["serde"]
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.6"
|
||||
app_units = "0.7"
|
||||
base64 = { optional = true, version = "0.6" }
|
||||
bincode = "1.0"
|
||||
bitflags = "1.0"
|
||||
byteorder = "1.0"
|
||||
cfg-if = "0.1.2"
|
||||
euclid = "0.18"
|
||||
euclid = "0.19"
|
||||
fxhash = "0.2.1"
|
||||
gleam = "0.6"
|
||||
image = { optional = true, version = "0.19" }
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
num-traits = "0.1.43"
|
||||
plane-split = "0.10"
|
||||
num-traits = "0.2"
|
||||
plane-split = "0.12"
|
||||
png = { optional = true, version = "0.12" }
|
||||
rayon = "1"
|
||||
ron = { optional = true, version = "0.1.7" }
|
||||
|
|
|
@ -70,7 +70,6 @@ void main(void) {
|
|||
#endif
|
||||
} else {
|
||||
bvec4 edge_mask = notEqual(edge_flags & ivec4(1, 2, 4, 8), ivec4(0));
|
||||
bool do_perspective_interpolation = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0;
|
||||
|
||||
vi = write_transform_vertex(
|
||||
local_segment_rect,
|
||||
|
@ -79,8 +78,7 @@ void main(void) {
|
|||
mix(vec4(0.0), vec4(1.0), edge_mask),
|
||||
ph.z,
|
||||
transform,
|
||||
pic_task,
|
||||
do_perspective_interpolation
|
||||
pic_task
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -92,7 +90,7 @@ void main(void) {
|
|||
// implies the other, for now.
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
write_clip(
|
||||
vi.screen_pos,
|
||||
vi.world_pos,
|
||||
clip_area
|
||||
);
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,7 @@ void brush_vs(
|
|||
) {
|
||||
PictureTask src_task = fetch_picture_task(user_data.x);
|
||||
vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
|
||||
vec2 uv = vi.snapped_device_pos +
|
||||
vec2 uv = snap_device_pos(vi) +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vUv = vec3(uv / texture_size, src_task.common_data.texture_layer_index);
|
||||
|
|
|
@ -11,7 +11,8 @@ varying vec2 vLocalPos;
|
|||
#endif
|
||||
|
||||
// Interpolated uv coordinates in xy, and layer in z.
|
||||
varying vec3 vUv;
|
||||
// W is 1 when perspective interpolation is enabled.
|
||||
varying vec4 vUv;
|
||||
// Normalized bounds of the source image in the texture.
|
||||
flat varying vec4 vUvBounds;
|
||||
// Normalized bounds of the source image in the texture, adjusted to avoid
|
||||
|
@ -106,6 +107,7 @@ void brush_vs(
|
|||
}
|
||||
|
||||
vUv.z = res.layer;
|
||||
vUv.w = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
|
||||
|
||||
// Handle case where the UV coords are inverted (e.g. from an
|
||||
// external image).
|
||||
|
@ -151,6 +153,10 @@ void brush_vs(
|
|||
vUv.xy = mix(uv0, uv1, f) - min_uv;
|
||||
vUv.xy /= texture_size;
|
||||
vUv.xy *= repeat.xy;
|
||||
if ((brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) == 0) {
|
||||
// Multiply by W to compensate for perspective interpolation.
|
||||
vUv.xy *= gl_Position.w;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_TEXTURE_RECT
|
||||
vUvBounds = vec4(0.0, 0.0, vec2(textureSize(sColor0)));
|
||||
|
@ -196,12 +202,14 @@ void brush_vs(
|
|||
|
||||
Fragment brush_fs() {
|
||||
vec2 uv_size = vUvBounds.zw - vUvBounds.xy;
|
||||
// Unapply the W scaler when no perspective interpolation is enabled.
|
||||
vec2 base_uv = vUv.xy * mix(gl_FragCoord.w, 1.0, vUv.w);
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
// This prevents the uv on the top and left parts of the primitive that was inflated
|
||||
// for anti-aliasing purposes from going beyound the range covered by the regular
|
||||
// (non-inflated) primitive.
|
||||
vec2 local_uv = max(vUv.xy, vec2(0.0));
|
||||
vec2 local_uv = max(base_uv, vec2(0.0));
|
||||
|
||||
// Handle horizontal and vertical repetitions.
|
||||
vec2 repeated_uv = mod(local_uv, uv_size) + vUvBounds.xy;
|
||||
|
@ -217,7 +225,7 @@ Fragment brush_fs() {
|
|||
}
|
||||
#else
|
||||
// Handle horizontal and vertical repetitions.
|
||||
vec2 repeated_uv = mod(vUv.xy, uv_size) + vUvBounds.xy;
|
||||
vec2 repeated_uv = mod(base_uv, uv_size) + vUvBounds.xy;
|
||||
#endif
|
||||
|
||||
// Clamp the uvs to avoid sampling artifacts.
|
||||
|
|
|
@ -23,17 +23,18 @@ void brush_vs(
|
|||
int brush_flags,
|
||||
vec4 unused
|
||||
) {
|
||||
vec2 snapped_device_pos = snap_device_pos(vi);
|
||||
vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
|
||||
vOp = user_data.x;
|
||||
|
||||
PictureTask src_task = fetch_picture_task(user_data.z);
|
||||
vec2 src_uv = vi.snapped_device_pos +
|
||||
vec2 src_uv = snapped_device_pos +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vSrcUv = vec3(src_uv / texture_size, src_task.common_data.texture_layer_index);
|
||||
|
||||
RenderTaskCommonData backdrop_task = fetch_render_task_common_data(user_data.y);
|
||||
vec2 backdrop_uv = vi.snapped_device_pos +
|
||||
vec2 backdrop_uv = snapped_device_pos +
|
||||
backdrop_task.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vBackdropUv = vec3(backdrop_uv / texture_size, backdrop_task.texture_layer_index);
|
||||
|
|
|
@ -27,7 +27,8 @@ vec2 clamp_rect(vec2 pt, RectWithSize rect) {
|
|||
|
||||
// TODO: convert back to RectWithEndPoint if driver issues are resolved, if ever.
|
||||
flat varying vec4 vClipMaskUvBounds;
|
||||
varying vec3 vClipMaskUv;
|
||||
// XY and W are homogeneous coordinates, Z is the layer index
|
||||
varying vec4 vClipMaskUv;
|
||||
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
@ -86,11 +87,15 @@ PrimitiveHeader fetch_prim_header(int index) {
|
|||
|
||||
struct VertexInfo {
|
||||
vec2 local_pos;
|
||||
vec2 screen_pos;
|
||||
float w;
|
||||
vec2 snapped_device_pos;
|
||||
vec2 snap_offset;
|
||||
vec4 world_pos;
|
||||
};
|
||||
|
||||
//Note: this function is unsafe for `vi.world_pos.w <= 0.0`
|
||||
vec2 snap_device_pos(VertexInfo vi) {
|
||||
return vi.world_pos.xy * uDevicePixelRatio / max(0.0, vi.world_pos.w) + vi.snap_offset;
|
||||
}
|
||||
|
||||
VertexInfo write_vertex(RectWithSize instance_rect,
|
||||
RectWithSize local_clip_rect,
|
||||
float z,
|
||||
|
@ -119,8 +124,7 @@ VertexInfo write_vertex(RectWithSize instance_rect,
|
|||
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
|
||||
|
||||
// Apply offsets for the render task to get correct screen location.
|
||||
vec2 snapped_device_pos = device_pos + snap_offset;
|
||||
vec2 final_pos = snapped_device_pos -
|
||||
vec2 final_pos = device_pos + snap_offset -
|
||||
task.content_origin +
|
||||
task.common_data.task_rect.p0;
|
||||
|
||||
|
@ -128,9 +132,8 @@ VertexInfo write_vertex(RectWithSize instance_rect,
|
|||
|
||||
VertexInfo vi = VertexInfo(
|
||||
clamped_local_pos,
|
||||
device_pos,
|
||||
world_pos.w,
|
||||
snapped_device_pos
|
||||
snap_offset,
|
||||
world_pos
|
||||
);
|
||||
|
||||
return vi;
|
||||
|
@ -161,8 +164,7 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
|
|||
vec4 clip_edge_mask,
|
||||
float z,
|
||||
Transform transform,
|
||||
PictureTask task,
|
||||
bool do_perspective_interpolation) {
|
||||
PictureTask task) {
|
||||
// Calculate a clip rect from local_rect + local clip
|
||||
RectWithEndpoint clip_rect = to_rect_with_endpoint(local_clip_rect);
|
||||
RectWithEndpoint segment_rect = to_rect_with_endpoint(local_segment_rect);
|
||||
|
@ -192,23 +194,17 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
|
|||
// Select the corner of the local rect that we are processing.
|
||||
vec2 local_pos = local_segment_rect.p0 + local_segment_rect.size * aPosition.xy;
|
||||
|
||||
// Transform the current vertex to the world cpace.
|
||||
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
|
||||
|
||||
// Convert the world positions to device pixel space.
|
||||
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
|
||||
vec2 task_offset = task.common_data.task_rect.p0 - task.content_origin;
|
||||
|
||||
// Force w = 1, if we don't want perspective interpolation (for
|
||||
// example, drawing a screen-space quad on an element with a
|
||||
// perspective transform).
|
||||
world_pos.w = mix(1.0, world_pos.w, do_perspective_interpolation);
|
||||
// Transform the current vertex to the world cpace.
|
||||
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
|
||||
vec4 final_pos = vec4(
|
||||
world_pos.xy * uDevicePixelRatio + task_offset * world_pos.w,
|
||||
z * world_pos.w,
|
||||
world_pos.w
|
||||
);
|
||||
|
||||
// We want the world space coords to be perspective divided by W.
|
||||
// We also want that to apply to any interpolators. However, we
|
||||
// want a constant Z across the primitive, since we're using it
|
||||
// for draw ordering - so scale by the W coord to ensure this.
|
||||
vec4 final_pos = vec4(device_pos + task_offset, z, 1.0) * world_pos.w;
|
||||
gl_Position = uTransform * final_pos;
|
||||
|
||||
init_transform_vs(mix(
|
||||
|
@ -219,36 +215,44 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
|
|||
|
||||
VertexInfo vi = VertexInfo(
|
||||
local_pos,
|
||||
device_pos,
|
||||
world_pos.w,
|
||||
device_pos
|
||||
vec2(0.0),
|
||||
world_pos
|
||||
);
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
void write_clip(vec2 global_pos, ClipArea area) {
|
||||
vec2 uv = global_pos +
|
||||
area.common_data.task_rect.p0 -
|
||||
area.screen_origin;
|
||||
void write_clip(vec4 world_pos, ClipArea area) {
|
||||
vec2 uv = world_pos.xy * uDevicePixelRatio +
|
||||
world_pos.w * (area.common_data.task_rect.p0 - area.screen_origin);
|
||||
vClipMaskUvBounds = vec4(
|
||||
area.common_data.task_rect.p0,
|
||||
area.common_data.task_rect.p0 + area.common_data.task_rect.size
|
||||
);
|
||||
vClipMaskUv = vec3(uv, area.common_data.texture_layer_index);
|
||||
vClipMaskUv = vec4(uv, area.common_data.texture_layer_index, world_pos.w);
|
||||
}
|
||||
#endif //WR_VERTEX_SHADER
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
float do_clip() {
|
||||
// anything outside of the mask is considered transparent
|
||||
bvec4 inside = lessThanEqual(
|
||||
vec4(vClipMaskUvBounds.xy, vClipMaskUv.xy),
|
||||
vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
|
||||
// check for the dummy bounds, which are given to the opaque objects
|
||||
return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
|
||||
all(inside) ? texelFetch(sCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
|
||||
if (vClipMaskUvBounds.xy == vClipMaskUvBounds.zw) {
|
||||
return 1.0;
|
||||
}
|
||||
// anything outside of the mask is considered transparent
|
||||
//Note: we assume gl_FragCoord.w == interpolated(1 / vClipMaskUv.w)
|
||||
vec2 mask_uv = vClipMaskUv.xy * gl_FragCoord.w;
|
||||
bvec4 inside = lessThanEqual(
|
||||
vec4(vClipMaskUvBounds.xy, mask_uv),
|
||||
vec4(mask_uv, vClipMaskUvBounds.zw));
|
||||
// bail out if the pixel is outside the valid bounds
|
||||
if (!all(inside)) {
|
||||
return 0.0;
|
||||
}
|
||||
// finally, the slow path - fetch the mask value from an image
|
||||
ivec3 tc = ivec3(mask_uv, vClipMaskUv.z);
|
||||
return texelFetch(sCacheA8, tc, 0).r;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_DITHERING
|
||||
|
|
|
@ -73,37 +73,33 @@ VertexInfo write_text_vertex(vec2 clamped_local_pos,
|
|||
// Convert the world positions to device pixel space.
|
||||
float device_scale = uDevicePixelRatio / world_pos.w;
|
||||
vec2 device_pos = world_pos.xy * device_scale;
|
||||
|
||||
// Apply offsets for the render task to get correct screen location.
|
||||
vec2 final_pos = device_pos -
|
||||
task.content_origin +
|
||||
task.common_data.task_rect.p0;
|
||||
vec2 snap_offset = vec2(0.0);
|
||||
|
||||
#if defined(WR_FEATURE_GLYPH_TRANSFORM)
|
||||
bool remove_subpx_offset = true;
|
||||
#else
|
||||
// Compute the snapping offset only if the scroll node transform is axis-aligned.
|
||||
bool remove_subpx_offset = transform.is_axis_aligned;
|
||||
#endif
|
||||
// Compute the snapping offset only if the scroll node transform is axis-aligned.
|
||||
if (remove_subpx_offset) {
|
||||
// Ensure the transformed text offset does not contain a subpixel translation
|
||||
// such that glyph snapping is stable for equivalent glyph subpixel positions.
|
||||
vec2 world_text_offset = mat2(transform.m) * text_offset;
|
||||
vec2 device_text_pos = (transform.m[3].xy + world_text_offset) * device_scale;
|
||||
final_pos += floor(device_text_pos + 0.5) - device_text_pos;
|
||||
snap_offset += floor(device_text_pos + 0.5) - device_text_pos;
|
||||
|
||||
#ifdef WR_FEATURE_GLYPH_TRANSFORM
|
||||
// For transformed subpixels, we just need to align the glyph origin to a device pixel.
|
||||
// The transformed text offset has already been snapped, so remove it from the glyph
|
||||
// origin when snapping the glyph.
|
||||
vec2 snap_offset = snap_rect.p0 - world_text_offset * device_scale;
|
||||
final_pos += floor(snap_offset + snap_bias) - snap_offset;
|
||||
vec2 rough_offset = snap_rect.p0 - world_text_offset * device_scale;
|
||||
snap_offset += floor(rough_offset + snap_bias) - rough_offset;
|
||||
#else
|
||||
// The transformed text offset has already been snapped, so remove it from the transform
|
||||
// when snapping the glyph.
|
||||
mat4 snap_transform = transform.m;
|
||||
snap_transform[3].xy = -world_text_offset;
|
||||
final_pos += compute_snap_offset(
|
||||
snap_offset += compute_snap_offset(
|
||||
clamped_local_pos,
|
||||
snap_transform,
|
||||
snap_rect,
|
||||
|
@ -112,13 +108,17 @@ VertexInfo write_text_vertex(vec2 clamped_local_pos,
|
|||
#endif
|
||||
}
|
||||
|
||||
// Apply offsets for the render task to get correct screen location.
|
||||
vec2 final_pos = device_pos + snap_offset -
|
||||
task.content_origin +
|
||||
task.common_data.task_rect.p0;
|
||||
|
||||
gl_Position = uTransform * vec4(final_pos, z, 1.0);
|
||||
|
||||
VertexInfo vi = VertexInfo(
|
||||
clamped_local_pos,
|
||||
device_pos,
|
||||
world_pos.w,
|
||||
final_pos
|
||||
snap_offset,
|
||||
world_pos
|
||||
);
|
||||
|
||||
return vi;
|
||||
|
@ -223,7 +223,7 @@ void main(void) {
|
|||
vec2 f = (vi.local_pos - glyph_rect.p0) / glyph_rect.size;
|
||||
#endif
|
||||
|
||||
write_clip(vi.screen_pos, clip_area);
|
||||
write_clip(vi.world_pos, clip_area);
|
||||
|
||||
switch (color_mode) {
|
||||
case COLOR_MODE_ALPHA:
|
||||
|
|
|
@ -1788,7 +1788,7 @@ impl ClipBatcher {
|
|||
) {
|
||||
let mut coordinate_system_id = coordinate_system_id;
|
||||
for work_item in clips.iter() {
|
||||
let info = clip_store.get(work_item.clip_sources_index);
|
||||
let info = &clip_store[work_item.clip_sources_index];
|
||||
let instance = ClipMaskInstance {
|
||||
render_task_address: task_address,
|
||||
transform_id: transforms.get_id(info.spatial_node_index),
|
||||
|
|
|
@ -9,10 +9,20 @@ use app_units::Au;
|
|||
use ellipse::Ellipse;
|
||||
use display_list_flattener::DisplayListFlattener;
|
||||
use gpu_types::{BorderInstance, BorderSegment, BrushFlags};
|
||||
use prim_store::{BrushKind, BrushPrimitive, BrushSegment};
|
||||
use prim_store::{BrushKind, BrushPrimitive, BrushSegment, VECS_PER_SEGMENT};
|
||||
use prim_store::{BorderSource, EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain};
|
||||
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||
use util::{lerp, RectHelpers};
|
||||
|
||||
// Using 2048 as the maximum radius in device space before which we
|
||||
// start stretching is up for debate.
|
||||
// the value must be chosen so that the corners will not use an
|
||||
// unreasonable amount of memory but should allow crisp corners in the
|
||||
// common cases.
|
||||
|
||||
/// Maximum resolution in device pixels at which borders are rasterized.
|
||||
pub const MAX_BORDER_RESOLUTION: u32 = 2048;
|
||||
|
||||
trait AuSizeConverter {
|
||||
fn to_au(&self) -> LayoutSizeAu;
|
||||
}
|
||||
|
@ -345,18 +355,24 @@ impl BorderCornerClipSource {
|
|||
1.0 - 2.0 * outer_scale.y,
|
||||
);
|
||||
|
||||
// No point in pushing more clips as it will blow up the maximum amount of
|
||||
// segments per primitive later down the road.
|
||||
// See #2915 for a better fix.
|
||||
let clip_limit = MAX_VERTEX_TEXTURE_WIDTH / VECS_PER_SEGMENT;
|
||||
let max_clip_count = self.max_clip_count.min(clip_limit);
|
||||
|
||||
match self.kind {
|
||||
BorderCornerClipKind::Dash => {
|
||||
// Get the correct dash arc length.
|
||||
let dash_arc_length =
|
||||
0.5 * self.ellipse.total_arc_length / self.max_clip_count as f32;
|
||||
0.5 * self.ellipse.total_arc_length / max_clip_count as f32;
|
||||
// Start the first dash at one quarter the length of a single dash
|
||||
// along the arc line. This is arbitrary but looks reasonable in
|
||||
// most cases. We need to spend some time working on a more
|
||||
// sophisticated dash placement algorithm that takes into account
|
||||
// the offset of the dashes along edge segments.
|
||||
let mut current_arc_length = 0.25 * dash_arc_length;
|
||||
for _ in 0 .. self.max_clip_count {
|
||||
for _ in 0 .. max_clip_count {
|
||||
let arc_length0 = current_arc_length;
|
||||
current_arc_length += dash_arc_length;
|
||||
|
||||
|
@ -401,7 +417,7 @@ impl BorderCornerClipSource {
|
|||
]);
|
||||
}
|
||||
}
|
||||
BorderCornerClipKind::Dot if self.max_clip_count == 1 => {
|
||||
BorderCornerClipKind::Dot if max_clip_count == 1 => {
|
||||
let dot_diameter = lerp(self.widths.width, self.widths.height, 0.5);
|
||||
dot_dash_data.push([
|
||||
self.widths.width / 2.0, self.widths.height / 2.0, 0.5 * dot_diameter, 0.,
|
||||
|
@ -422,7 +438,7 @@ impl BorderCornerClipSource {
|
|||
self.widths.height,
|
||||
));
|
||||
|
||||
for dot_index in 0 .. self.max_clip_count {
|
||||
for dot_index in 0 .. max_clip_count {
|
||||
let prev_forward_pos = *forward_dots.last().unwrap();
|
||||
let prev_back_pos = *back_dots.last().unwrap();
|
||||
|
||||
|
@ -927,6 +943,23 @@ impl BorderRenderTaskInfo {
|
|||
|
||||
instances
|
||||
}
|
||||
|
||||
/// Computes the maximum scale that we allow for this set of border radii.
|
||||
/// capping the scale will result in rendering very large corners at a lower
|
||||
/// resolution and stretching them, so they will have the right shape, but
|
||||
/// blurrier.
|
||||
pub fn get_max_scale(radii: &BorderRadius) -> LayoutToDeviceScale {
|
||||
let r = radii.top_left.width
|
||||
.max(radii.top_left.height)
|
||||
.max(radii.top_right.width)
|
||||
.max(radii.top_right.height)
|
||||
.max(radii.bottom_left.width)
|
||||
.max(radii.bottom_left.height)
|
||||
.max(radii.bottom_right.width)
|
||||
.max(radii.bottom_right.height);
|
||||
|
||||
LayoutToDeviceScale::new(MAX_BORDER_RESOLUTION as f32 / r)
|
||||
}
|
||||
}
|
||||
|
||||
fn add_brush_segment(
|
||||
|
|
|
@ -14,8 +14,9 @@ use gpu_types::BoxShadowStretchMode;
|
|||
use prim_store::{ClipData, ImageMaskData};
|
||||
use render_task::to_cache_size;
|
||||
use resource_cache::{ImageRequest, ResourceCache};
|
||||
use util::{LayoutToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
|
||||
use util::{extract_inner_rect_safe, pack_as_float, recycle_vec};
|
||||
use util::{LayoutToWorldFastTransform, MaxRect, TransformedRectKind};
|
||||
use util::{calculate_screen_bounding_rect, extract_inner_rect_safe, pack_as_float, recycle_vec};
|
||||
use std::{iter, ops};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -28,13 +29,13 @@ pub struct ClipStore {
|
|||
}
|
||||
|
||||
impl ClipStore {
|
||||
pub fn new() -> ClipStore {
|
||||
pub fn new() -> Self {
|
||||
ClipStore {
|
||||
clip_sources: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recycle(self) -> ClipStore {
|
||||
pub fn recycle(self) -> Self {
|
||||
ClipStore {
|
||||
clip_sources: recycle_vec(self.clip_sources),
|
||||
}
|
||||
|
@ -45,12 +46,17 @@ impl ClipStore {
|
|||
self.clip_sources.push(clip_sources);
|
||||
index
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, index: ClipSourcesIndex) -> &ClipSources {
|
||||
impl ops::Index<ClipSourcesIndex> for ClipStore {
|
||||
type Output = ClipSources;
|
||||
fn index(&self, index: ClipSourcesIndex) -> &Self::Output {
|
||||
&self.clip_sources[index.0]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, index: ClipSourcesIndex) -> &mut ClipSources {
|
||||
impl ops::IndexMut<ClipSourcesIndex> for ClipStore {
|
||||
fn index_mut(&mut self, index: ClipSourcesIndex) -> &mut Self::Output {
|
||||
&mut self.clip_sources[index.0]
|
||||
}
|
||||
}
|
||||
|
@ -63,51 +69,77 @@ pub struct LineDecorationClipSource {
|
|||
wavy_line_thickness: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClipRegion {
|
||||
pub main: LayoutRect,
|
||||
pub image_mask: Option<ImageMask>,
|
||||
pub complex_clips: Vec<ComplexClipRegion>,
|
||||
|
||||
pub struct ComplexTranslateIter<I> {
|
||||
source: I,
|
||||
offset: LayoutVector2D,
|
||||
}
|
||||
|
||||
impl ClipRegion {
|
||||
impl<I: Iterator<Item = ComplexClipRegion>> Iterator for ComplexTranslateIter<I> {
|
||||
type Item = ComplexClipRegion;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.source
|
||||
.next()
|
||||
.map(|mut complex| {
|
||||
complex.rect = complex.rect.translate(&self.offset);
|
||||
complex
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClipRegion<I> {
|
||||
pub main: LayoutRect,
|
||||
pub image_mask: Option<ImageMask>,
|
||||
pub complex_clips: I,
|
||||
}
|
||||
|
||||
impl<J> ClipRegion<ComplexTranslateIter<J>> {
|
||||
pub fn create_for_clip_node(
|
||||
rect: LayoutRect,
|
||||
mut complex_clips: Vec<ComplexClipRegion>,
|
||||
complex_clips: J,
|
||||
mut image_mask: Option<ImageMask>,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) -> ClipRegion {
|
||||
let rect = rect.translate(reference_frame_relative_offset);
|
||||
|
||||
) -> Self
|
||||
where
|
||||
J: Iterator<Item = ComplexClipRegion>
|
||||
{
|
||||
if let Some(ref mut image_mask) = image_mask {
|
||||
image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset);
|
||||
}
|
||||
|
||||
for complex_clip in complex_clips.iter_mut() {
|
||||
complex_clip.rect = complex_clip.rect.translate(reference_frame_relative_offset);
|
||||
}
|
||||
|
||||
ClipRegion {
|
||||
main: rect,
|
||||
main: rect.translate(reference_frame_relative_offset),
|
||||
image_mask,
|
||||
complex_clips,
|
||||
complex_clips: ComplexTranslateIter {
|
||||
source: complex_clips,
|
||||
offset: *reference_frame_relative_offset,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClipRegion<Option<ComplexClipRegion>> {
|
||||
pub fn create_for_clip_node_with_local_clip(
|
||||
local_clip: &LocalClip,
|
||||
reference_frame_relative_offset: &LayoutVector2D
|
||||
) -> ClipRegion {
|
||||
let complex_clips = match *local_clip {
|
||||
LocalClip::Rect(_) => Vec::new(),
|
||||
LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
|
||||
};
|
||||
ClipRegion::create_for_clip_node(
|
||||
*local_clip.clip_rect(),
|
||||
complex_clips,
|
||||
None,
|
||||
reference_frame_relative_offset
|
||||
)
|
||||
) -> Self {
|
||||
ClipRegion {
|
||||
main: local_clip
|
||||
.clip_rect()
|
||||
.translate(reference_frame_relative_offset),
|
||||
image_mask: None,
|
||||
complex_clips: match *local_clip {
|
||||
LocalClip::Rect(_) => None,
|
||||
LocalClip::RoundedRect(_, ref region) => {
|
||||
Some(ComplexClipRegion {
|
||||
rect: region.rect.translate(reference_frame_relative_offset),
|
||||
radii: region.radii,
|
||||
mode: region.mode,
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,6 +312,92 @@ impl ClipSource {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
struct BoundsAccumulator {
|
||||
local_outer: Option<LayoutRect>,
|
||||
local_inner: Option<LayoutRect>,
|
||||
can_calculate_inner_rect: bool,
|
||||
can_calculate_outer_rect: bool,
|
||||
}
|
||||
|
||||
impl BoundsAccumulator {
|
||||
fn new() -> Self {
|
||||
BoundsAccumulator {
|
||||
local_outer: Some(LayoutRect::max_rect()),
|
||||
local_inner: Some(LayoutRect::max_rect()),
|
||||
can_calculate_inner_rect: true,
|
||||
can_calculate_outer_rect: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, source: &ClipSource) {
|
||||
// Depending on the complexity of the clip, we may either know the outer and/or inner
|
||||
// rect, or neither or these. In the case of a clip-out, we currently set the mask bounds
|
||||
// to be unknown. This is conservative, but ensures correctness. In the future we can make
|
||||
// this a lot more clever with some proper region handling.
|
||||
if !self.can_calculate_inner_rect {
|
||||
return
|
||||
}
|
||||
|
||||
match *source {
|
||||
ClipSource::Image(ref mask) => {
|
||||
if !mask.repeat {
|
||||
self.can_calculate_outer_rect = true;
|
||||
self.local_outer = self.local_outer.and_then(|r| r.intersection(&mask.rect));
|
||||
}
|
||||
self.local_inner = None;
|
||||
}
|
||||
ClipSource::Rectangle(rect, mode) => {
|
||||
// Once we encounter a clip-out, we just assume the worst
|
||||
// case clip mask size, for now.
|
||||
if mode == ClipMode::ClipOut {
|
||||
self.can_calculate_inner_rect = false;
|
||||
return
|
||||
}
|
||||
|
||||
self.can_calculate_outer_rect = true;
|
||||
self.local_outer = self.local_outer.and_then(|r| r.intersection(&rect));
|
||||
self.local_inner = self.local_inner.and_then(|r| r.intersection(&rect));
|
||||
}
|
||||
ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
|
||||
// Once we encounter a clip-out, we just assume the worst
|
||||
// case clip mask size, for now.
|
||||
if mode == ClipMode::ClipOut {
|
||||
self.can_calculate_inner_rect = false;
|
||||
return
|
||||
}
|
||||
|
||||
self.can_calculate_outer_rect = true;
|
||||
self.local_outer = self.local_outer.and_then(|r| r.intersection(rect));
|
||||
|
||||
let inner_rect = extract_inner_rect_safe(rect, radius);
|
||||
self.local_inner = self.local_inner
|
||||
.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
|
||||
}
|
||||
ClipSource::BoxShadow(..) |
|
||||
ClipSource::LineDecoration(..) => {
|
||||
self.can_calculate_inner_rect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(self) -> (LayoutRect, Option<LayoutRect>) {
|
||||
(
|
||||
if self.can_calculate_inner_rect {
|
||||
self.local_inner.unwrap_or_else(LayoutRect::zero)
|
||||
} else {
|
||||
LayoutRect::zero()
|
||||
},
|
||||
if self.can_calculate_outer_rect {
|
||||
Some(self.local_outer.unwrap_or_else(LayoutRect::zero))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClipSources {
|
||||
pub clips: Vec<(ClipSource, GpuCacheHandle)>,
|
||||
|
@ -291,20 +409,24 @@ pub struct ClipSources {
|
|||
}
|
||||
|
||||
impl ClipSources {
|
||||
pub fn new(
|
||||
clips: Vec<ClipSource>,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
) -> Self {
|
||||
let (local_inner_rect, local_outer_rect) = Self::calculate_inner_and_outer_rects(&clips);
|
||||
pub fn new<I>(clip_iter: I, spatial_node_index: SpatialNodeIndex) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = ClipSource>,
|
||||
{
|
||||
let mut clips = Vec::new();
|
||||
let mut bounds_accum = BoundsAccumulator::new();
|
||||
let mut has_image_or_line_decoration_clip = false;
|
||||
let mut only_rectangular_clips = true;
|
||||
|
||||
let has_image_or_line_decoration_clip =
|
||||
clips.iter().any(|clip| clip.is_image_or_line_decoration_clip());
|
||||
let only_rectangular_clips =
|
||||
!has_image_or_line_decoration_clip && clips.iter().all(|clip| clip.is_rect());
|
||||
let clips = clips
|
||||
.into_iter()
|
||||
.map(|clip| (clip, GpuCacheHandle::new()))
|
||||
.collect();
|
||||
for clip in clip_iter {
|
||||
bounds_accum.add(&clip);
|
||||
has_image_or_line_decoration_clip |= clip.is_image_or_line_decoration_clip();
|
||||
only_rectangular_clips &= clip.is_rect();
|
||||
clips.push((clip, GpuCacheHandle::new()));
|
||||
}
|
||||
|
||||
only_rectangular_clips &= !has_image_or_line_decoration_clip;
|
||||
let (local_inner_rect, local_outer_rect) = bounds_accum.finish();
|
||||
|
||||
ClipSources {
|
||||
clips,
|
||||
|
@ -316,105 +438,31 @@ impl ClipSources {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_region(
|
||||
region: ClipRegion,
|
||||
pub fn from_region<I>(
|
||||
region: ClipRegion<I>,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
) -> ClipSources {
|
||||
let mut clips = Vec::new();
|
||||
|
||||
if let Some(info) = region.image_mask {
|
||||
clips.push(ClipSource::Image(info));
|
||||
}
|
||||
|
||||
clips.push(ClipSource::Rectangle(region.main, ClipMode::Clip));
|
||||
|
||||
for complex in region.complex_clips {
|
||||
clips.push(ClipSource::new_rounded_rect(
|
||||
) -> ClipSources
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>
|
||||
{
|
||||
let clip_rect = iter::once(ClipSource::Rectangle(region.main, ClipMode::Clip));
|
||||
let clip_image = region.image_mask.map(ClipSource::Image);
|
||||
let clips_complex = region.complex_clips
|
||||
.into_iter()
|
||||
.map(|complex| ClipSource::new_rounded_rect(
|
||||
complex.rect,
|
||||
complex.radii,
|
||||
complex.mode,
|
||||
));
|
||||
}
|
||||
|
||||
ClipSources::new(clips, spatial_node_index)
|
||||
let clips_all = clip_rect.chain(clip_image).chain(clips_complex);
|
||||
ClipSources::new(clips_all, spatial_node_index)
|
||||
}
|
||||
|
||||
pub fn clips(&self) -> &[(ClipSource, GpuCacheHandle)] {
|
||||
&self.clips
|
||||
}
|
||||
|
||||
fn calculate_inner_and_outer_rects(clips: &Vec<ClipSource>) -> (LayoutRect, Option<LayoutRect>) {
|
||||
if clips.is_empty() {
|
||||
return (LayoutRect::zero(), None);
|
||||
}
|
||||
|
||||
// Depending on the complexity of the clip, we may either know the outer and/or inner
|
||||
// rect, or neither or these. In the case of a clip-out, we currently set the mask bounds
|
||||
// to be unknown. This is conservative, but ensures correctness. In the future we can make
|
||||
// this a lot more clever with some proper region handling.
|
||||
let mut local_outer = Some(LayoutRect::max_rect());
|
||||
let mut local_inner = local_outer;
|
||||
let mut can_calculate_inner_rect = true;
|
||||
let mut can_calculate_outer_rect = false;
|
||||
for source in clips {
|
||||
match *source {
|
||||
ClipSource::Image(ref mask) => {
|
||||
if !mask.repeat {
|
||||
can_calculate_outer_rect = true;
|
||||
local_outer = local_outer.and_then(|r| r.intersection(&mask.rect));
|
||||
}
|
||||
local_inner = None;
|
||||
}
|
||||
ClipSource::Rectangle(rect, mode) => {
|
||||
// Once we encounter a clip-out, we just assume the worst
|
||||
// case clip mask size, for now.
|
||||
if mode == ClipMode::ClipOut {
|
||||
can_calculate_inner_rect = false;
|
||||
break;
|
||||
}
|
||||
|
||||
can_calculate_outer_rect = true;
|
||||
local_outer = local_outer.and_then(|r| r.intersection(&rect));
|
||||
local_inner = local_inner.and_then(|r| r.intersection(&rect));
|
||||
}
|
||||
ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
|
||||
// Once we encounter a clip-out, we just assume the worst
|
||||
// case clip mask size, for now.
|
||||
if mode == ClipMode::ClipOut {
|
||||
can_calculate_inner_rect = false;
|
||||
break;
|
||||
}
|
||||
|
||||
can_calculate_outer_rect = true;
|
||||
local_outer = local_outer.and_then(|r| r.intersection(rect));
|
||||
|
||||
let inner_rect = extract_inner_rect_safe(rect, radius);
|
||||
local_inner = local_inner
|
||||
.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
|
||||
}
|
||||
ClipSource::BoxShadow(..) |
|
||||
ClipSource::LineDecoration(..) => {
|
||||
can_calculate_inner_rect = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let outer = if can_calculate_outer_rect {
|
||||
Some(local_outer.unwrap_or_else(LayoutRect::zero))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let inner = if can_calculate_inner_rect {
|
||||
local_inner.unwrap_or_else(LayoutRect::zero)
|
||||
} else {
|
||||
LayoutRect::zero()
|
||||
};
|
||||
|
||||
(inner, outer)
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
gpu_cache: &mut GpuCache,
|
||||
|
@ -523,7 +571,8 @@ impl ClipSources {
|
|||
// rectangle so that we can do screen inner rectangle optimizations for these kind of
|
||||
// cilps.
|
||||
let can_calculate_inner_rect =
|
||||
transform.preserves_2d_axis_alignment() && !transform.has_perspective_component();
|
||||
transform.kind() == TransformedRectKind::AxisAligned &&
|
||||
!transform.has_perspective_component();
|
||||
let screen_inner_rect = if can_calculate_inner_rect {
|
||||
calculate_screen_bounding_rect(transform, &self.local_inner_rect, device_pixel_scale, screen_rect)
|
||||
.unwrap_or(DeviceIntRect::zero())
|
||||
|
|
|
@ -37,7 +37,7 @@ impl ClipNode {
|
|||
clip_chains: &mut [ClipChain],
|
||||
spatial_nodes: &[SpatialNode],
|
||||
) {
|
||||
let clip_sources = clip_store.get_mut(self.clip_sources_index);
|
||||
let clip_sources = &mut clip_store[self.clip_sources_index];
|
||||
clip_sources.update(gpu_cache, resource_cache, device_pixel_scale);
|
||||
let spatial_node = &spatial_nodes[clip_sources.spatial_node_index.0];
|
||||
|
||||
|
@ -60,10 +60,8 @@ impl ClipNode {
|
|||
clip_sources_index: self.clip_sources_index,
|
||||
coordinate_system_id: spatial_node.coordinate_system_id,
|
||||
},
|
||||
local_clip_rect: spatial_node
|
||||
.coordinate_system_relative_transform
|
||||
.transform_rect(&local_outer_rect)
|
||||
.expect("clip node transform is not valid"),
|
||||
local_clip_rect: local_outer_rect
|
||||
.translate(&spatial_node.coordinate_system_relative_offset),
|
||||
screen_outer_rect,
|
||||
screen_inner_rect,
|
||||
prev: None,
|
||||
|
|
|
@ -14,7 +14,7 @@ use print_tree::{PrintTree, PrintTreePrinter};
|
|||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo};
|
||||
use util::{LayoutFastTransform, LayoutToWorldFastTransform};
|
||||
use util::LayoutToWorldFastTransform;
|
||||
|
||||
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
||||
|
||||
|
@ -103,8 +103,8 @@ pub struct TransformUpdateState {
|
|||
/// coordinate systems which are relatively axis aligned.
|
||||
pub current_coordinate_system_id: CoordinateSystemId,
|
||||
|
||||
/// Transform from the coordinate system that started this compatible coordinate system.
|
||||
pub coordinate_system_relative_transform: LayoutFastTransform,
|
||||
/// Offset from the coordinate system that started this compatible coordinate system.
|
||||
pub coordinate_system_relative_offset: LayoutVector2D,
|
||||
|
||||
/// True if this node is transformed by an invertible transform. If not, display items
|
||||
/// transformed by this node will not be displayed and display items not transformed by this
|
||||
|
@ -242,7 +242,7 @@ impl ClipScrollTree {
|
|||
nearest_scrolling_ancestor_offset: LayoutVector2D::zero(),
|
||||
nearest_scrolling_ancestor_viewport: LayoutRect::zero(),
|
||||
current_coordinate_system_id: CoordinateSystemId::root(),
|
||||
coordinate_system_relative_transform: LayoutFastTransform::identity(),
|
||||
coordinate_system_relative_offset: LayoutVector2D::zero(),
|
||||
invertible: true,
|
||||
};
|
||||
|
||||
|
|
|
@ -71,16 +71,18 @@ pub struct GpuFrameProfile<T> {
|
|||
samplers: QuerySet<GpuSampler<T>>,
|
||||
frame_id: FrameId,
|
||||
inside_frame: bool,
|
||||
ext_debug_marker: bool
|
||||
}
|
||||
|
||||
impl<T> GpuFrameProfile<T> {
|
||||
fn new(gl: Rc<gl::Gl>) -> Self {
|
||||
fn new(gl: Rc<gl::Gl>, ext_debug_marker: bool) -> Self {
|
||||
GpuFrameProfile {
|
||||
gl,
|
||||
timers: QuerySet::new(),
|
||||
samplers: QuerySet::new(),
|
||||
frame_id: FrameId::new(0),
|
||||
inside_frame: false,
|
||||
ext_debug_marker
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +142,7 @@ impl<T: NamedTag> GpuFrameProfile<T> {
|
|||
fn start_timer(&mut self, tag: T) -> GpuTimeQuery {
|
||||
self.finish_timer();
|
||||
|
||||
let marker = GpuMarker::new(&self.gl, tag.get_label());
|
||||
let marker = GpuMarker::new(&self.gl, tag.get_label(), self.ext_debug_marker);
|
||||
|
||||
if let Some(query) = self.timers.add(GpuTimer { tag, time_ns: 0 }) {
|
||||
self.gl.begin_query(gl::TIME_ELAPSED, query);
|
||||
|
@ -187,19 +189,21 @@ pub struct GpuProfiler<T> {
|
|||
gl: Rc<gl::Gl>,
|
||||
frames: Vec<GpuFrameProfile<T>>,
|
||||
next_frame: usize,
|
||||
ext_debug_marker: bool
|
||||
}
|
||||
|
||||
impl<T> GpuProfiler<T> {
|
||||
pub fn new(gl: Rc<gl::Gl>) -> Self {
|
||||
pub fn new(gl: Rc<gl::Gl>, ext_debug_marker: bool) -> Self {
|
||||
const MAX_PROFILE_FRAMES: usize = 4;
|
||||
let frames = (0 .. MAX_PROFILE_FRAMES)
|
||||
.map(|_| GpuFrameProfile::new(Rc::clone(&gl)))
|
||||
.map(|_| GpuFrameProfile::new(Rc::clone(&gl), ext_debug_marker))
|
||||
.collect();
|
||||
|
||||
GpuProfiler {
|
||||
gl,
|
||||
next_frame: 0,
|
||||
frames,
|
||||
ext_debug_marker
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,33 +267,42 @@ impl<T: NamedTag> GpuProfiler<T> {
|
|||
}
|
||||
|
||||
pub fn start_marker(&mut self, label: &str) -> GpuMarker {
|
||||
GpuMarker::new(&self.gl, label)
|
||||
GpuMarker::new(&self.gl, label, self.ext_debug_marker)
|
||||
}
|
||||
|
||||
pub fn place_marker(&mut self, label: &str) {
|
||||
GpuMarker::fire(&self.gl, label)
|
||||
GpuMarker::fire(&self.gl, label, self.ext_debug_marker)
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct GpuMarker {
|
||||
gl: Rc<gl::Gl>,
|
||||
gl: Option<Rc<gl::Gl>>
|
||||
}
|
||||
|
||||
impl GpuMarker {
|
||||
fn new(gl: &Rc<gl::Gl>, message: &str) -> Self {
|
||||
fn new(gl: &Rc<gl::Gl>, message: &str, ext_debug_marker: bool) -> Self {
|
||||
let gl = if ext_debug_marker {
|
||||
gl.push_group_marker_ext(message);
|
||||
GpuMarker { gl: Rc::clone(gl) }
|
||||
Some(Rc::clone(gl))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
GpuMarker { gl }
|
||||
}
|
||||
|
||||
fn fire(gl: &Rc<gl::Gl>, message: &str) {
|
||||
fn fire(gl: &Rc<gl::Gl>, message: &str, ext_debug_marker: bool) {
|
||||
if ext_debug_marker {
|
||||
gl.insert_event_marker_ext(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GpuMarker {
|
||||
fn drop(&mut self) {
|
||||
self.gl.pop_group_marker_ext();
|
||||
if let Some(ref gl) = self.gl {
|
||||
gl.pop_group_marker_ext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,22 +224,22 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
complex_clips: ItemRange<ComplexClipRegion>,
|
||||
) -> Vec<ComplexClipRegion> {
|
||||
if complex_clips.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
self.scene.get_display_list_for_pipeline(pipeline_id).get(complex_clips).collect()
|
||||
) -> impl 'a + Iterator<Item = ComplexClipRegion> {
|
||||
//Note: we could make this a bit more complex to early out
|
||||
// on `complex_clips.is_empty()` if it's worth it
|
||||
self.scene
|
||||
.get_display_list_for_pipeline(pipeline_id)
|
||||
.get(complex_clips)
|
||||
}
|
||||
|
||||
fn get_clip_chain_items(
|
||||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
items: ItemRange<ClipId>,
|
||||
) -> Vec<ClipId> {
|
||||
if items.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
self.scene.get_display_list_for_pipeline(pipeline_id).get(items).collect()
|
||||
) -> impl 'a + Iterator<Item = ClipId> {
|
||||
self.scene
|
||||
.get_display_list_for_pipeline(pipeline_id)
|
||||
.get(items)
|
||||
}
|
||||
|
||||
fn flatten_root(&mut self, pipeline: &'a ScenePipeline, frame_size: &LayoutSize) {
|
||||
|
@ -685,8 +685,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
}
|
||||
SpecificDisplayItem::ClipChain(ref info) => {
|
||||
let items = self.get_clip_chain_items(pipeline_id, item.clip_chain_items())
|
||||
.iter()
|
||||
.map(|id| self.id_to_index_mapper.get_clip_node_index(*id))
|
||||
.map(|id| self.id_to_index_mapper.get_clip_node_index(id))
|
||||
.collect();
|
||||
let parent = match info.parent {
|
||||
Some(id) => Some(
|
||||
|
@ -1241,12 +1240,15 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn add_clip_node(
|
||||
pub fn add_clip_node<I>(
|
||||
&mut self,
|
||||
new_node_id: ClipId,
|
||||
parent_id: ClipId,
|
||||
clip_region: ClipRegion,
|
||||
) -> ClipChainIndex {
|
||||
clip_region: ClipRegion<I>,
|
||||
) -> ClipChainIndex
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>
|
||||
{
|
||||
let parent_clip_chain_index = self.id_to_index_mapper.get_clip_chain_index(&parent_id);
|
||||
let spatial_node = self.id_to_index_mapper.get_spatial_node_index(parent_id);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ pub struct PictureState {
|
|||
}
|
||||
|
||||
impl PictureState {
|
||||
pub fn new() -> PictureState {
|
||||
pub fn new() -> Self {
|
||||
PictureState {
|
||||
tasks: Vec::new(),
|
||||
has_non_root_coord_system: false,
|
||||
|
@ -117,7 +117,7 @@ pub struct PrimitiveRunContext<'a> {
|
|||
pub clip_chain: &'a ClipChain,
|
||||
pub scroll_node: &'a SpatialNode,
|
||||
pub spatial_node_index: SpatialNodeIndex,
|
||||
pub transform: Transform,
|
||||
pub transform: Transform<'a>,
|
||||
pub local_clip_rect: LayoutRect,
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ impl<'a> PrimitiveRunContext<'a> {
|
|||
scroll_node: &'a SpatialNode,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
local_clip_rect: LayoutRect,
|
||||
transform: Transform,
|
||||
transform: Transform<'a>,
|
||||
) -> Self {
|
||||
PrimitiveRunContext {
|
||||
clip_chain,
|
||||
|
|
|
@ -8,7 +8,7 @@ use clip_scroll_tree::SpatialNodeIndex;
|
|||
use gpu_cache::{GpuCacheAddress, GpuDataRequest};
|
||||
use prim_store::{EdgeAaSegmentMask, Transform};
|
||||
use render_task::RenderTaskAddress;
|
||||
use util::{MatrixHelpers, TransformedRectKind};
|
||||
use util::{LayoutToWorldFastTransform, TransformedRectKind};
|
||||
|
||||
// Contains type that must exactly match the same structures declared in GLSL.
|
||||
|
||||
|
@ -374,12 +374,12 @@ impl TransformPaletteId {
|
|||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[repr(C)]
|
||||
pub struct TransformData {
|
||||
pub transform: LayoutToWorldTransform,
|
||||
pub inv_transform: WorldToLayoutTransform,
|
||||
transform: LayoutToWorldTransform,
|
||||
inv_transform: WorldToLayoutTransform,
|
||||
}
|
||||
|
||||
impl TransformData {
|
||||
pub fn invalid() -> Self {
|
||||
fn invalid() -> Self {
|
||||
TransformData {
|
||||
transform: LayoutToWorldTransform::identity(),
|
||||
inv_transform: WorldToLayoutTransform::identity(),
|
||||
|
@ -389,7 +389,7 @@ impl TransformData {
|
|||
|
||||
// Extra data stored about each transform palette entry.
|
||||
pub struct TransformMetadata {
|
||||
pub transform_kind: TransformedRectKind,
|
||||
transform_kind: TransformedRectKind,
|
||||
}
|
||||
|
||||
// Stores a contiguous list of TransformData structs, that
|
||||
|
@ -405,38 +405,60 @@ pub struct TransformPalette {
|
|||
}
|
||||
|
||||
impl TransformPalette {
|
||||
pub fn new(spatial_node_count: usize) -> TransformPalette {
|
||||
pub fn new(spatial_node_count: usize) -> Self {
|
||||
TransformPalette {
|
||||
transforms: Vec::with_capacity(spatial_node_count),
|
||||
metadata: Vec::with_capacity(spatial_node_count),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the local -> world transform for a given spatial
|
||||
// node in the transform palette.
|
||||
pub fn set(
|
||||
&mut self,
|
||||
index: SpatialNodeIndex,
|
||||
data: TransformData,
|
||||
) {
|
||||
let index = index.0 as usize;
|
||||
|
||||
#[inline]
|
||||
fn grow(&mut self, index: SpatialNodeIndex) {
|
||||
// Pad the vectors out if they are not long enough to
|
||||
// account for this index. This can occur, for instance,
|
||||
// when we stop recursing down the CST due to encountering
|
||||
// a node with an invalid transform.
|
||||
while index >= self.transforms.len() {
|
||||
while self.transforms.len() <= index.0 as usize {
|
||||
self.transforms.push(TransformData::invalid());
|
||||
self.metadata.push(TransformMetadata {
|
||||
transform_kind: TransformedRectKind::AxisAligned,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Store the transform itself, along with metadata about it.
|
||||
self.metadata[index] = TransformMetadata {
|
||||
transform_kind: data.transform.transform_kind(),
|
||||
pub fn invalidate(&mut self, index: SpatialNodeIndex) {
|
||||
self.grow(index);
|
||||
self.metadata[index.0 as usize] = TransformMetadata {
|
||||
transform_kind: TransformedRectKind::AxisAligned,
|
||||
};
|
||||
self.transforms[index] = data;
|
||||
self.transforms[index.0 as usize] = TransformData::invalid();
|
||||
}
|
||||
|
||||
// Set the local -> world transform for a given spatial
|
||||
// node in the transform palette.
|
||||
pub fn set(
|
||||
&mut self, index: SpatialNodeIndex, fast_transform: &LayoutToWorldFastTransform,
|
||||
) -> bool {
|
||||
self.grow(index);
|
||||
|
||||
match fast_transform.inverse() {
|
||||
Some(inverted) => {
|
||||
// Store the transform itself, along with metadata about it.
|
||||
self.metadata[index.0 as usize] = TransformMetadata {
|
||||
transform_kind: fast_transform.kind()
|
||||
};
|
||||
// Write the data that will be made available to the GPU for this node.
|
||||
self.transforms[index.0 as usize] = TransformData {
|
||||
transform: fast_transform.to_transform().into_owned(),
|
||||
inv_transform: inverted.to_transform().into_owned(),
|
||||
};
|
||||
true
|
||||
}
|
||||
None => {
|
||||
self.invalidate(index);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the relevant information about a given transform that is
|
||||
|
@ -448,14 +470,13 @@ impl TransformPalette {
|
|||
&self,
|
||||
index: SpatialNodeIndex,
|
||||
) -> Transform {
|
||||
let index = index.0;
|
||||
let transform = &self.transforms[index];
|
||||
let metadata = &self.metadata[index];
|
||||
let data = &self.transforms[index.0 as usize];
|
||||
let metadata = &self.metadata[index.0 as usize];
|
||||
|
||||
Transform {
|
||||
m: transform.transform,
|
||||
m: &data.transform,
|
||||
transform_kind: metadata.transform_kind,
|
||||
backface_is_visible: transform.transform.is_backface_visible(),
|
||||
backface_is_visible: data.transform.is_backface_visible(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ pub struct HitTestClipNode {
|
|||
|
||||
impl HitTestClipNode {
|
||||
fn new(node: &ClipNode, clip_store: &ClipStore) -> Self {
|
||||
let clips = clip_store.get(node.clip_sources_index);
|
||||
let clips = &clip_store[node.clip_sources_index];
|
||||
let regions = clips.clips().iter().map(|source| {
|
||||
match source.0 {
|
||||
ClipSource::Rectangle(ref rect, mode) => HitTestRegion::Rectangle(*rect, mode),
|
||||
|
|
|
@ -63,8 +63,8 @@ impl ScrollNodeAndClipChain {
|
|||
// the information in the clip-scroll tree. However, if we decide
|
||||
// to rasterize a picture in local space, then this will be the
|
||||
// transform relative to that picture's coordinate system.
|
||||
pub struct Transform {
|
||||
pub m: LayoutToWorldTransform,
|
||||
pub struct Transform<'a> {
|
||||
pub m: &'a LayoutToWorldTransform,
|
||||
pub backface_is_visible: bool,
|
||||
pub transform_kind: TransformedRectKind,
|
||||
}
|
||||
|
@ -1495,7 +1495,9 @@ impl PrimitiveStore {
|
|||
// scale factor from the world transform to get an appropriately
|
||||
// sized border task.
|
||||
let world_scale = LayoutToWorldScale::new(1.0);
|
||||
let scale = world_scale * frame_context.device_pixel_scale;
|
||||
let mut scale = world_scale * frame_context.device_pixel_scale;
|
||||
let max_scale = BorderRenderTaskInfo::get_max_scale(&border.radius);
|
||||
scale.0 = scale.0.min(max_scale.0);
|
||||
let scale_au = Au::from_f32_px(scale.0);
|
||||
let needs_update = scale_au != cache_key.scale;
|
||||
let mut new_segments = Vec::new();
|
||||
|
@ -1572,7 +1574,7 @@ impl PrimitiveStore {
|
|||
PrimitiveKind::TextRun => {
|
||||
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||
// The transform only makes sense for screen space rasterization
|
||||
let transform = prim_run_context.scroll_node.world_content_transform.into();
|
||||
let transform = prim_run_context.scroll_node.world_content_transform.to_transform();
|
||||
text.prepare_for_render(
|
||||
frame_context.device_pixel_scale,
|
||||
&transform,
|
||||
|
@ -2062,7 +2064,7 @@ impl PrimitiveStore {
|
|||
continue;
|
||||
}
|
||||
|
||||
let local_clips = frame_state.clip_store.get(clip_item.clip_sources_index);
|
||||
let local_clips = &frame_state.clip_store[clip_item.clip_sources_index];
|
||||
rect_clips_only = rect_clips_only && local_clips.only_rectangular_clips;
|
||||
|
||||
// TODO(gw): We can easily extend the segment builder to support these clip sources in
|
||||
|
@ -2289,7 +2291,7 @@ impl PrimitiveStore {
|
|||
let extra_clip = {
|
||||
let metadata = &self.cpu_metadata[prim_index.0];
|
||||
metadata.clip_sources_index.map(|clip_sources_index| {
|
||||
let prim_clips = frame_state.clip_store.get_mut(clip_sources_index);
|
||||
let prim_clips = &mut frame_state.clip_store[clip_sources_index];
|
||||
prim_clips.update(
|
||||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
|
@ -2964,8 +2966,8 @@ fn get_local_clip_rect_for_nodes(
|
|||
})
|
||||
}
|
||||
)
|
||||
.and_then(|local_rect| {
|
||||
scroll_node.coordinate_system_relative_transform.unapply(&local_rect)
|
||||
.map(|local_rect| {
|
||||
local_rect.translate(&-scroll_node.coordinate_system_relative_offset)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -403,7 +403,7 @@ impl RenderTask {
|
|||
// whether a ClipSources contains any box-shadows and skip
|
||||
// this iteration for the majority of cases.
|
||||
for clip_item in &clips {
|
||||
let clip_sources = clip_store.get_mut(clip_item.clip_sources_index);
|
||||
let clip_sources = &mut clip_store[clip_item.clip_sources_index];
|
||||
for &mut (ref mut clip, _) in &mut clip_sources.clips {
|
||||
match *clip {
|
||||
ClipSource::BoxShadow(ref mut info) => {
|
||||
|
|
|
@ -1767,7 +1767,8 @@ impl Renderer {
|
|||
}
|
||||
})?;
|
||||
|
||||
let gpu_profile = GpuProfiler::new(Rc::clone(device.rc_gl()));
|
||||
let ext_debug_marker = device.supports_extension("GL_EXT_debug_marker");
|
||||
let gpu_profile = GpuProfiler::new(Rc::clone(device.rc_gl()), ext_debug_marker);
|
||||
#[cfg(feature = "capture")]
|
||||
let read_fbo = device.create_fbo_for_external_texture(0);
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollLoc
|
|||
use api::{ScrollSensitivity, StickyOffsetBounds};
|
||||
use clip_scroll_tree::{CoordinateSystemId, SpatialNodeIndex, TransformUpdateState};
|
||||
use euclid::SideOffsets2D;
|
||||
use gpu_types::{TransformData, TransformPalette};
|
||||
use gpu_types::TransformPalette;
|
||||
use scene::SceneProperties;
|
||||
use util::{LayoutFastTransform, LayoutToWorldFastTransform, TransformedRectKind};
|
||||
use util::{LayoutFastTransform, LayoutToWorldFastTransform, MatrixHelpers, TransformedRectKind};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SpatialNodeType {
|
||||
|
@ -66,7 +66,7 @@ pub struct SpatialNode {
|
|||
/// The transformation from the coordinate system which established our compatible coordinate
|
||||
/// system (same coordinate system id) and us. This can change via scroll offsets and via new
|
||||
/// reference frame transforms.
|
||||
pub coordinate_system_relative_transform: LayoutFastTransform,
|
||||
pub coordinate_system_relative_offset: LayoutVector2D,
|
||||
}
|
||||
|
||||
impl SpatialNode {
|
||||
|
@ -85,7 +85,7 @@ impl SpatialNode {
|
|||
node_type,
|
||||
invertible: true,
|
||||
coordinate_system_id: CoordinateSystemId(0),
|
||||
coordinate_system_relative_transform: LayoutFastTransform::identity(),
|
||||
coordinate_system_relative_offset: LayoutVector2D::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,25 +204,11 @@ impl SpatialNode {
|
|||
node_index: SpatialNodeIndex,
|
||||
) {
|
||||
if !self.invertible {
|
||||
transform_palette.set(node_index, TransformData::invalid());
|
||||
transform_palette.invalidate(node_index);
|
||||
return;
|
||||
}
|
||||
|
||||
let inv_transform = match self.world_content_transform.inverse() {
|
||||
Some(inverted) => inverted.to_transform(),
|
||||
None => {
|
||||
transform_palette.set(node_index, TransformData::invalid());
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let data = TransformData {
|
||||
transform: self.world_content_transform.into(),
|
||||
inv_transform,
|
||||
};
|
||||
|
||||
// Write the data that will be made available to the GPU for this node.
|
||||
transform_palette.set(node_index, data);
|
||||
transform_palette.set(node_index, &self.world_content_transform);
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
|
@ -239,12 +225,7 @@ impl SpatialNode {
|
|||
}
|
||||
|
||||
self.update_transform(state, next_coordinate_system_id, scene_properties);
|
||||
|
||||
self.transform_kind = if self.world_content_transform.preserves_2d_axis_alignment() {
|
||||
TransformedRectKind::AxisAligned
|
||||
} else {
|
||||
TransformedRectKind::Complex
|
||||
};
|
||||
self.transform_kind = self.world_content_transform.kind();
|
||||
|
||||
// If this node is a reference frame, we check if it has a non-invertible matrix.
|
||||
// For non-reference-frames we assume that they will produce only additional
|
||||
|
@ -292,14 +273,17 @@ impl SpatialNode {
|
|||
|
||||
// Try to update our compatible coordinate system transform. If we cannot, start a new
|
||||
// incompatible coordinate system.
|
||||
match state.coordinate_system_relative_transform.update(relative_transform) {
|
||||
Some(offset) => self.coordinate_system_relative_transform = offset,
|
||||
None => {
|
||||
self.coordinate_system_relative_transform = LayoutFastTransform::identity();
|
||||
if relative_transform.is_simple_2d_translation() {
|
||||
self.coordinate_system_relative_offset =
|
||||
state.coordinate_system_relative_offset +
|
||||
LayoutVector2D::new(relative_transform.m41, relative_transform.m42);
|
||||
} else {
|
||||
// If we break 2D axis alignment or have a perspective component, we need to start a
|
||||
// new incompatible coordinate system with which we cannot share clips without masking.
|
||||
self.coordinate_system_relative_offset = LayoutVector2D::zero();
|
||||
state.current_coordinate_system_id = *next_coordinate_system_id;
|
||||
next_coordinate_system_id.advance();
|
||||
}
|
||||
}
|
||||
|
||||
self.coordinate_system_id = state.current_coordinate_system_id;
|
||||
}
|
||||
|
@ -330,8 +314,8 @@ impl SpatialNode {
|
|||
};
|
||||
|
||||
let added_offset = state.parent_accumulated_scroll_offset + sticky_offset + scroll_offset;
|
||||
self.coordinate_system_relative_transform =
|
||||
state.coordinate_system_relative_transform.offset(added_offset);
|
||||
self.coordinate_system_relative_offset =
|
||||
state.coordinate_system_relative_offset + added_offset;
|
||||
|
||||
if let SpatialNodeType::StickyFrame(ref mut info) = self.node_type {
|
||||
info.current_offset = sticky_offset;
|
||||
|
@ -478,8 +462,7 @@ impl SpatialNode {
|
|||
SpatialNodeType::ReferenceFrame(ref info) => {
|
||||
state.parent_reference_frame_transform = self.world_viewport_transform;
|
||||
state.parent_accumulated_scroll_offset = LayoutVector2D::zero();
|
||||
state.coordinate_system_relative_transform =
|
||||
self.coordinate_system_relative_transform.clone();
|
||||
state.coordinate_system_relative_offset = self.coordinate_system_relative_offset;
|
||||
let translation = -info.origin_in_parent_reference_frame;
|
||||
state.nearest_scrolling_ancestor_viewport =
|
||||
state.nearest_scrolling_ancestor_viewport
|
||||
|
|
|
@ -11,6 +11,8 @@ use euclid::{HomogeneousVector};
|
|||
use num_traits::Zero;
|
||||
use plane_split::{Clipper, Plane, Polygon};
|
||||
use std::{i32, f32};
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
||||
// Matches the definition of SK_ScalarNearlyZero in Skia.
|
||||
const NEARLY_ZERO: f32 = 1.0 / 4096.0;
|
||||
|
@ -486,11 +488,20 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
FastTransform::Transform { transform, inverse, is_2d}
|
||||
}
|
||||
|
||||
pub fn to_transform(&self) -> TypedTransform3D<f32, Src, Dst> {
|
||||
pub fn kind(&self) -> TransformedRectKind {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) =>
|
||||
TypedTransform3D::create_translation(offset.x, offset.y, 0.0),
|
||||
FastTransform::Transform { transform, .. } => transform
|
||||
FastTransform::Offset(_) => TransformedRectKind::AxisAligned,
|
||||
FastTransform::Transform { ref transform, .. } if transform.preserves_2d_axis_alignment() => TransformedRectKind::AxisAligned,
|
||||
FastTransform::Transform { .. } => TransformedRectKind::Complex,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_transform(&self) -> Cow<TypedTransform3D<f32, Src, Dst>> {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => Cow::Owned(
|
||||
TypedTransform3D::create_translation(offset.x, offset.y, 0.0)
|
||||
),
|
||||
FastTransform::Transform { ref transform, .. } => Cow::Borrowed(transform),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,15 +539,6 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn preserves_2d_axis_alignment(&self) -> bool {
|
||||
match *self {
|
||||
FastTransform::Offset(..) => true,
|
||||
FastTransform::Transform { ref transform, .. } =>
|
||||
transform.preserves_2d_axis_alignment(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn has_perspective_component(&self) -> bool {
|
||||
match *self {
|
||||
|
@ -596,17 +598,6 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn offset(&self, new_offset: TypedVector2D<f32, Src>) -> Self {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => FastTransform::Offset(offset + new_offset),
|
||||
FastTransform::Transform { ref transform, .. } => {
|
||||
let transform = transform.pre_translate(new_offset.to_3d());
|
||||
FastTransform::with_transform(transform)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn post_translate(&self, new_offset: TypedVector2D<f32, Dst>) -> Self {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => {
|
||||
|
@ -635,16 +626,6 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self, transform: TypedTransform3D<f32, Src, Dst>) -> Option<Self> {
|
||||
if transform.is_simple_2d_translation() {
|
||||
Some(self.offset(TypedVector2D::new(transform.m41, transform.m42)))
|
||||
} else {
|
||||
// If we break 2D axis alignment or have a perspective component, we need to start a
|
||||
// new incompatible coordinate system with which we cannot share clips without masking.
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
|
||||
|
@ -653,12 +634,6 @@ impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst>
|
|||
}
|
||||
}
|
||||
|
||||
impl<Src, Dst> Into<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
|
||||
fn into(self) -> TypedTransform3D<f32, Src, Dst> {
|
||||
self.to_transform()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
|
||||
fn from(vector: TypedVector2D<f32, Src>) -> Self {
|
||||
FastTransform::with_vector(vector)
|
||||
|
|
|
@ -12,12 +12,12 @@ serialize = []
|
|||
deserialize = []
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.6"
|
||||
app_units = "0.7"
|
||||
bincode = "1.0"
|
||||
bitflags = "1.0"
|
||||
byteorder = "1.2.1"
|
||||
ipc-channel = {version = "0.10.0", optional = true}
|
||||
euclid = { version = "0.18", features = ["serde"] }
|
||||
euclid = { version = "0.19", features = ["serde"] }
|
||||
serde = { version = "=1.0.66", features = ["rc"] }
|
||||
serde_derive = { version = "=1.0.66", features = ["deserialize_in_place"] }
|
||||
serde_bytes = "0.10"
|
||||
|
|
|
@ -123,7 +123,7 @@ pub struct AuxIter<'a, T> {
|
|||
impl BuiltDisplayListDescriptor {}
|
||||
|
||||
impl BuiltDisplayList {
|
||||
pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> BuiltDisplayList {
|
||||
pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self {
|
||||
BuiltDisplayList { data, descriptor }
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ license = "MPL-2.0"
|
|||
[dependencies]
|
||||
rayon = "1"
|
||||
thread_profiler = "0.1.1"
|
||||
euclid = { version = "0.18", features = ["serde"] }
|
||||
app_units = "0.6"
|
||||
euclid = { version = "0.19", features = ["serde"] }
|
||||
app_units = "0.7"
|
||||
gleam = "0.6"
|
||||
log = "0.4"
|
||||
nsstring = { path = "../../servo/support/gecko/nsstring" }
|
||||
|
|
|
@ -1 +1 @@
|
|||
8a4fe66528aa362721e4048aac3cd5abf7faaf2c
|
||||
7a1b919e37d6cd0155077aa90f98cfcdf9fa5bae
|
||||
|
|
|
@ -10,10 +10,10 @@ base64 = "0.6"
|
|||
bincode = "1.0"
|
||||
byteorder = "1.0"
|
||||
env_logger = { version = "0.5", optional = true }
|
||||
euclid = "0.18"
|
||||
euclid = "0.19"
|
||||
gleam = "0.6"
|
||||
glutin = "0.17"
|
||||
app_units = "0.6"
|
||||
app_units = "0.7"
|
||||
image = "0.19"
|
||||
clap = { version = "2", features = ["yaml"] }
|
||||
lazy_static = "1"
|
||||
|
|
Загрузка…
Ссылка в новой задаче