--- a/gfx/webrender/examples/common/boilerplate.rs
+++ b/gfx/webrender/examples/common/boilerplate.rs
@@ -29,17 +29,17 @@ impl RenderNotifier for Notifier {
})
}
fn wake_up(&self) {
#[cfg(not(target_os = "android"))]
let _ = self.events_proxy.wakeup();
}
- fn new_document_ready(&self, _: DocumentId, _scrolled: bool, _composite_needed: bool) {
+ fn new_frame_ready(&self, _: DocumentId, _scrolled: bool, _composite_needed: bool) {
self.wake_up();
}
}
pub trait HandyDandyRectBuilder {
fn to(&self, x2: i32, y2: i32) -> LayoutRect;
fn by(&self, w: i32, h: i32) -> LayoutRect;
}
--- a/gfx/webrender/examples/multiwindow.rs
+++ b/gfx/webrender/examples/multiwindow.rs
@@ -32,17 +32,17 @@ impl RenderNotifier for Notifier {
})
}
fn wake_up(&self) {
#[cfg(not(target_os = "android"))]
let _ = self.events_proxy.wakeup();
}
- fn new_document_ready(&self, _: DocumentId, _scrolled: bool, _composite_needed: bool) {
+ fn new_frame_ready(&self, _: DocumentId, _scrolled: bool, _composite_needed: bool) {
self.wake_up();
}
}
struct Window {
events_loop: glutin::EventsLoop, //TODO: share events loop?
window: glutin::GlWindow,
renderer: webrender::Renderer,
--- a/gfx/webrender/res/brush.glsl
+++ b/gfx/webrender/res/brush.glsl
@@ -152,23 +152,36 @@ void main(void) {
pic_task,
segment_data[1]
);
}
#endif
#ifdef WR_FRAGMENT_SHADER
-vec4 brush_fs();
+struct Fragment {
+ vec4 color;
+#ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
+ vec4 blend;
+#endif
+};
+
+Fragment brush_fs();
void main(void) {
// Run the specific brush FS code to output the color.
- vec4 color = brush_fs();
+ Fragment frag = brush_fs();
#ifdef WR_FEATURE_ALPHA_PASS
// Apply the clip mask
- color *= do_clip();
+ float clip_alpha = do_clip();
+
+ frag.color *= clip_alpha;
+
+ #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
+ oFragBlend = frag.blend * clip_alpha;
+ #endif
#endif
// TODO(gw): Handle pre-multiply common code here as required.
- oFragColor = color;
+ oFragColor = frag.color;
}
#endif
--- a/gfx/webrender/res/brush_blend.glsl
+++ b/gfx/webrender/res/brush_blend.glsl
@@ -117,21 +117,21 @@ vec3 Invert(vec3 Cs, float amount) {
vec3 Brightness(vec3 Cs, float amount) {
// Apply the brightness factor.
// Resulting color needs to be clamped to output range
// since we are pre-multiplying alpha in the shader.
return clamp(Cs.rgb * amount, vec3(0.0), vec3(1.0));
}
-vec4 brush_fs() {
+Fragment brush_fs() {
vec4 Cs = texture(sColor0, vUv);
if (Cs.a == 0.0) {
- return vec4(0.0); // could also `discard`
+ return Fragment(vec4(0.0)); // could also `discard`
}
// Un-premultiply the input.
float alpha = Cs.a;
vec3 color = Cs.rgb / Cs.a;
switch (vOp) {
case 0:
@@ -152,11 +152,11 @@ vec4 brush_fs() {
color = vColorMat * color + vColorOffset;
}
// Fail-safe to ensure that we don't sample outside the rendered
// portion of a blend source.
alpha *= point_inside_rect(vUv.xy, vUvClipBounds.xy, vUvClipBounds.zw);
// Pre-multiply the alpha into the output value.
- return alpha * vec4(color, 1.0);
+ return Fragment(alpha * vec4(color, 1.0));
}
#endif
--- a/gfx/webrender/res/brush_image.glsl
+++ b/gfx/webrender/res/brush_image.glsl
@@ -107,16 +107,20 @@ void brush_vs(
vec2 f;
#ifdef WR_FEATURE_ALPHA_PASS
int color_mode = user_data.y >> 16;
int raster_space = user_data.y & 0xffff;
ImageBrushData image_data = fetch_image_data(prim_address);
+ if (color_mode == COLOR_MODE_FROM_PASS) {
+ color_mode = uMode;
+ }
+
// Derive the texture coordinates for this image, based on
// whether the source image is a local-space or screen-space
// image.
switch (raster_space) {
case RASTER_SCREEN: {
ImageBrushExtraData extra_data = fetch_image_extra_data(user_data.z);
vec2 snapped_device_pos;
@@ -195,18 +199,18 @@ void brush_vs(
}
vLocalPos = vi.local_pos;
#endif
}
#endif
#ifdef WR_FRAGMENT_SHADER
-vec4 brush_fs() {
+Fragment brush_fs() {
vec2 uv_size = vUvBounds.zw - vUvBounds.xy;
#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));
@@ -227,19 +231,27 @@ vec4 brush_fs() {
vec2 repeated_uv = mod(vUv.xy, uv_size) + vUvBounds.xy;
#endif
// Clamp the uvs to avoid sampling artifacts.
vec2 uv = clamp(repeated_uv, vUvSampleBounds.xy, vUvSampleBounds.zw);
vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vUv.z));
+ Fragment frag;
+
#ifdef WR_FEATURE_ALPHA_PASS
float alpha = init_transform_fs(vLocalPos);
texel.rgb = texel.rgb * vMaskSwizzle.x + texel.aaa * vMaskSwizzle.y;
- vec4 color = vColor * texel * alpha;
+
+ vec4 alpha_mask = texel * alpha;
+ frag.color = vColor * alpha_mask;
+
+ #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
+ frag.blend = alpha_mask * vColor.a;
+ #endif
#else
- vec4 color = texel;
+ frag.color = texel;
#endif
- return color;
+ return frag;
}
#endif
--- a/gfx/webrender/res/brush_linear_gradient.glsl
+++ b/gfx/webrender/res/brush_linear_gradient.glsl
@@ -65,17 +65,17 @@ void brush_vs(
#ifdef WR_FEATURE_ALPHA_PASS
vTileRepeat = tile_repeat.xy;
vLocalPos = vi.local_pos;
#endif
}
#endif
#ifdef WR_FRAGMENT_SHADER
-vec4 brush_fs() {
+Fragment brush_fs() {
#ifdef WR_FEATURE_ALPHA_PASS
// Handle top and left inflated edges (see brush_image).
vec2 local_pos = max(vPos, vec2(0.0));
// Apply potential horizontal and vertical repetitions.
vec2 pos = mod(local_pos, vRepeatedSize);
@@ -97,11 +97,11 @@ vec4 brush_fs() {
vec4 color = sample_gradient(vGradientAddress,
offset,
vGradientRepeat);
#ifdef WR_FEATURE_ALPHA_PASS
color *= init_transform_fs(vLocalPos);
#endif
- return color;
+ return Fragment(color);
}
#endif
--- a/gfx/webrender/res/brush_mix_blend.glsl
+++ b/gfx/webrender/res/brush_mix_blend.glsl
@@ -191,25 +191,25 @@ const int MixBlendMode_HardLight = 8;
const int MixBlendMode_SoftLight = 9;
const int MixBlendMode_Difference = 10;
const int MixBlendMode_Exclusion = 11;
const int MixBlendMode_Hue = 12;
const int MixBlendMode_Saturation = 13;
const int MixBlendMode_Color = 14;
const int MixBlendMode_Luminosity = 15;
-vec4 brush_fs() {
+Fragment brush_fs() {
vec4 Cb = textureLod(sCacheRGBA8, vBackdropUv, 0.0);
vec4 Cs = textureLod(sCacheRGBA8, vSrcUv, 0.0);
if (Cb.a == 0.0) {
- return Cs;
+ return Fragment(Cs);
}
if (Cs.a == 0.0) {
- return vec4(0.0);
+ return Fragment(vec4(0.0));
}
// The mix-blend-mode functions assume no premultiplied alpha
Cb.rgb /= Cb.a;
Cs.rgb /= Cs.a;
// Return yellow if none of the branches match (shouldn't happen).
vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
@@ -270,11 +270,11 @@ vec4 brush_fs() {
default: break;
}
result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
result.a = Cs.a;
result.rgb *= result.a;
- return result;
+ return Fragment(result);
}
#endif
--- a/gfx/webrender/res/brush_radial_gradient.glsl
+++ b/gfx/webrender/res/brush_radial_gradient.glsl
@@ -68,17 +68,17 @@ void brush_vs(
#ifdef WR_FEATURE_ALPHA_PASS
vTileRepeat = tile_repeat.xy;
vLocalPos = vi.local_pos;
#endif
}
#endif
#ifdef WR_FRAGMENT_SHADER
-vec4 brush_fs() {
+Fragment brush_fs() {
#ifdef WR_FEATURE_ALPHA_PASS
// Handle top and left inflated edges (see brush_image).
vec2 local_pos = max(vPos, vec2(0.0));
// Apply potential horizontal and vertical repetitions.
vec2 pos = mod(local_pos, vRepeatedSize);
@@ -136,11 +136,11 @@ vec4 brush_fs() {
vec4 color = sample_gradient(vGradientAddress,
offset,
vGradientRepeat);
#ifdef WR_FEATURE_ALPHA_PASS
color *= init_transform_fs(vLocalPos);
#endif
- return color;
+ return Fragment(color);
}
#endif
--- a/gfx/webrender/res/brush_solid.glsl
+++ b/gfx/webrender/res/brush_solid.glsl
@@ -37,16 +37,16 @@ void brush_vs(
#ifdef WR_FEATURE_ALPHA_PASS
vLocalPos = vi.local_pos;
#endif
}
#endif
#ifdef WR_FRAGMENT_SHADER
-vec4 brush_fs() {
+Fragment brush_fs() {
vec4 color = vColor;
#ifdef WR_FEATURE_ALPHA_PASS
color *= init_transform_fs(vLocalPos);
#endif
- return color;
+ return Fragment(color);
}
#endif
--- a/gfx/webrender/res/brush_yuv_image.glsl
+++ b/gfx/webrender/res/brush_yuv_image.glsl
@@ -130,17 +130,17 @@ const mat3 YuvColorMatrix = mat3(
// The matrix is stored in column-major.
const mat3 YuvColorMatrix = mat3(
1.16438, 1.16438, 1.16438,
0.0 , -0.21325, 2.11240,
1.79274, -0.53291, 0.0
);
#endif
-vec4 brush_fs() {
+Fragment brush_fs() {
vec3 yuv_value;
#if defined (WR_FEATURE_YUV_PLANAR)
// The yuv_planar format should have this third texture coordinate.
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
vec2 uv_u = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
vec2 uv_v = clamp(vUv_V.xy, vUvBounds_V.xy, vUvBounds_V.zw);
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
@@ -164,11 +164,11 @@ vec4 brush_fs() {
// See the YuvColorMatrix definition for an explanation of where the constants come from.
vec3 rgb = YuvColorMatrix * (yuv_value - vec3(0.06275, 0.50196, 0.50196));
vec4 color = vec4(rgb, 1.0);
#ifdef WR_FEATURE_ALPHA_PASS
color *= init_transform_fs(vLocalPos);
#endif
- return color;
+ return Fragment(color);
}
#endif
--- a/gfx/webrender/res/cs_clip_border.glsl
+++ b/gfx/webrender/res/cs_clip_border.glsl
@@ -1,14 +1,17 @@
/* 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/. */
#include shared,clip_shared
+in vec4 aDashOrDot0;
+in vec4 aDashOrDot1;
+
varying vec3 vPos;
flat varying vec2 vClipCenter;
flat varying vec4 vPoint_Tangent0;
flat varying vec4 vPoint_Tangent1;
flat varying vec3 vDotParams;
flat varying vec2 vAlphaMask;
@@ -41,40 +44,43 @@ BorderCorner fetch_border_corner(ivec2 a
}
// Per-dash clip information.
struct BorderClipDash {
vec4 point_tangent_0;
vec4 point_tangent_1;
};
-BorderClipDash fetch_border_clip_dash(ivec2 address, int segment) {
- vec4 data[2] = fetch_from_resource_cache_2_direct(address + ivec2(2 + 2 * (segment - 1), 0));
- return BorderClipDash(data[0], data[1]);
+BorderClipDash fetch_border_clip_dash(ivec2 address) {
+ return BorderClipDash(aDashOrDot0, aDashOrDot1);
}
// Per-dot clip information.
struct BorderClipDot {
vec3 center_radius;
};
-BorderClipDot fetch_border_clip_dot(ivec2 address, int segment) {
- vec4 data = fetch_from_resource_cache_1_direct(address + ivec2(2 + (segment - 1), 0));
- return BorderClipDot(data.xyz);
+BorderClipDot fetch_border_clip_dot(ivec2 address) {
+ return BorderClipDot(aDashOrDot0.xyz);
}
void main(void) {
ClipMaskInstance cmi = fetch_clip_item();
ClipArea area = fetch_clip_area(cmi.render_task_address);
ClipScrollNode scroll_node = fetch_clip_scroll_node(cmi.scroll_node_id);
// Fetch the header information for this corner clip.
BorderCorner corner = fetch_border_corner(cmi.clip_data_address);
vClipCenter = corner.clip_center;
+ // Get local vertex position for the corner rect.
+ // TODO(gw): We could reduce the number of pixels written here by calculating a tight
+ // fitting bounding box of the dash itself like we do for dots below.
+ vec2 pos = corner.rect.p0 + aPosition.xy * corner.rect.size;
+
if (cmi.segment == 0) {
// The first segment is used to zero out the border corner.
vAlphaMask = vec2(0.0);
vDotParams = vec3(0.0);
vPoint_Tangent0 = vec4(1.0);
vPoint_Tangent1 = vec4(1.0);
} else {
vec2 sign_modifier;
@@ -93,43 +99,49 @@ void main(void) {
break;
default:
sign_modifier = vec2(0.0);
};
switch (corner.clip_mode) {
case CLIP_MODE_DASH: {
// Fetch the information about this particular dash.
- BorderClipDash dash = fetch_border_clip_dash(cmi.clip_data_address, cmi.segment);
+ BorderClipDash dash = fetch_border_clip_dash(cmi.clip_data_address);
vPoint_Tangent0 = dash.point_tangent_0 * sign_modifier.xyxy;
vPoint_Tangent1 = dash.point_tangent_1 * sign_modifier.xyxy;
vDotParams = vec3(0.0);
vAlphaMask = vec2(0.0, 1.0);
break;
}
case CLIP_MODE_DOT: {
- BorderClipDot cdot = fetch_border_clip_dot(cmi.clip_data_address, cmi.segment);
+ BorderClipDot cdot = fetch_border_clip_dot(cmi.clip_data_address);
vPoint_Tangent0 = vec4(1.0);
vPoint_Tangent1 = vec4(1.0);
vDotParams = vec3(cdot.center_radius.xy * sign_modifier, cdot.center_radius.z);
vAlphaMask = vec2(1.0, 1.0);
+
+ // Generate a tighter bounding rect for dots based on their position. Dot
+ // centers are given relative to clip center, so we need to move the dot
+ // rectangle into the clip space with an origin at the top left. First,
+ // we expand the radius slightly to ensure we get full coverage on all the pixels
+ // of the dots.
+ float expanded_radius = cdot.center_radius.z + 2.0;
+ pos = (vClipCenter + vDotParams.xy - vec2(expanded_radius));
+ pos += (aPosition.xy * vec2(expanded_radius * 2.0));
+ pos = clamp(pos, corner.rect.p0, corner.rect.p0 + corner.rect.size);
+
break;
}
default:
vPoint_Tangent0 = vPoint_Tangent1 = vec4(1.0);
vDotParams = vec3(0.0);
vAlphaMask = vec2(0.0);
}
}
- // Get local vertex position for the corner rect.
- // TODO(gw): We could reduce the number of pixels written here
- // by calculating a tight fitting bounding box of the dash itself.
- vec2 pos = corner.rect.p0 + aPosition.xy * corner.rect.size;
-
// Transform to world pos
vec4 world_pos = scroll_node.transform * vec4(pos, 0.0, 1.0);
world_pos.xyz /= world_pos.w;
// Scale into device pixels.
vec2 device_pos = world_pos.xy * uDevicePixelRatio;
// Position vertex within the render task area.
--- a/gfx/webrender/res/prim_shared.glsl
+++ b/gfx/webrender/res/prim_shared.glsl
@@ -38,16 +38,17 @@ varying vec3 vClipMaskUv;
#ifdef WR_VERTEX_SHADER
#define VECS_PER_LOCAL_CLIP_RECT 1
#define VECS_PER_PRIM_HEADER 2
#define VECS_PER_TEXT_RUN 3
#define VECS_PER_GRADIENT_STOP 2
+#define COLOR_MODE_FROM_PASS 0
#define COLOR_MODE_ALPHA 1
#define COLOR_MODE_SUBPX_CONST_COLOR 2
#define COLOR_MODE_SUBPX_BG_PASS0 3
#define COLOR_MODE_SUBPX_BG_PASS1 4
#define COLOR_MODE_SUBPX_BG_PASS2 5
#define COLOR_MODE_SUBPX_DUAL_SOURCE 6
#define COLOR_MODE_BITMAP 7
#define COLOR_MODE_COLOR_BITMAP 8
--- a/gfx/webrender/res/ps_text_run.glsl
+++ b/gfx/webrender/res/ps_text_run.glsl
@@ -59,17 +59,22 @@ VertexInfo write_text_vertex(vec2 clampe
}
void main(void) {
Primitive prim = load_primitive();
TextRun text = fetch_text_run(prim.specific_prim_address);
int glyph_index = prim.user_data0;
int resource_address = prim.user_data1;
- int subpx_dir = prim.user_data2;
+ int subpx_dir = prim.user_data2 >> 16;
+ int color_mode = prim.user_data2 & 0xffff;
+
+ if (color_mode == COLOR_MODE_FROM_PASS) {
+ color_mode = uMode;
+ }
Glyph glyph = fetch_glyph(prim.specific_prim_address,
glyph_index,
subpx_dir);
GlyphResource res = fetch_glyph_resource(resource_address);
#ifdef WR_FEATURE_GLYPH_TRANSFORM
// Transform from local space to glyph space.
@@ -118,17 +123,17 @@ void main(void) {
vec2 f = (transform * vi.local_pos - glyph_rect.p0) / glyph_rect.size;
vUvClip = vec4(f, 1.0 - f);
#else
vec2 f = (vi.local_pos - glyph_rect.p0) / glyph_rect.size;
#endif
write_clip(vi.screen_pos, prim.clip_area);
- switch (uMode) {
+ switch (color_mode) {
case COLOR_MODE_ALPHA:
case COLOR_MODE_BITMAP:
vMaskSwizzle = vec2(0.0, 1.0);
vColor = text.color;
break;
case COLOR_MODE_SUBPX_BG_PASS2:
case COLOR_MODE_SUBPX_DUAL_SOURCE:
vMaskSwizzle = vec2(1.0, 0.0);
--- a/gfx/webrender/src/batch.rs
+++ b/gfx/webrender/src/batch.rs
@@ -1,25 +1,26 @@
/* 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 api::{AlphaType, ClipMode, DeviceIntRect, DeviceIntSize};
-use api::{DeviceUintRect, DeviceUintPoint, DeviceUintSize, ExternalImageType, FilterOp, ImageRendering, LayerRect};
+use api::{DeviceUintRect, DeviceUintPoint, DeviceUintSize, ExternalImageType, FilterOp, ImageRendering, LayoutRect};
use api::{DeviceIntPoint, SubpixelDirection, YuvColorSpace, YuvFormat};
-use api::{LayerToWorldTransform, WorldPixel};
+use api::{LayoutToWorldTransform, WorldPixel};
use border::{BorderCornerInstance, BorderCornerSide, BorderEdgeKind};
use clip::{ClipSource, ClipStore, ClipWorkItem};
use clip_scroll_tree::{CoordinateSystemId};
use euclid::{TypedTransform3D, vec3};
use glyph_rasterizer::GlyphFormat;
use gpu_cache::{GpuCache, GpuCacheAddress};
-use gpu_types::{BrushFlags, BrushInstance, ClipChainRectIndex, ZBufferId, ZBufferIdGenerator};
-use gpu_types::{ClipMaskInstance, ClipScrollNodeIndex, RasterizationSpace};
-use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveInstance};
+use gpu_types::{BrushFlags, BrushInstance, ClipChainRectIndex, ClipMaskBorderCornerDotDash};
+use gpu_types::{ClipMaskInstance, ClipScrollNodeIndex, CompositePrimitiveInstance};
+use gpu_types::{PrimitiveInstance, RasterizationSpace, SimplePrimitiveInstance, ZBufferId};
+use gpu_types::ZBufferIdGenerator;
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
use picture::{PictureCompositeMode, PicturePrimitive, PictureSurface};
use picture::{IMAGE_BRUSH_BLOCKS, IMAGE_BRUSH_EXTRA_BLOCKS};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PictureIndex, PrimitiveRun};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
use renderer::{BlendMode, ImageBufferKind};
@@ -1150,41 +1151,66 @@ impl AlphaBatchBuilder {
],
};
let kind = BatchKind::Transformable(
transform_kind,
TransformBatchKind::TextRun(glyph_format),
);
- let blend_mode = match glyph_format {
+ let (blend_mode, color_mode) = match glyph_format {
GlyphFormat::Subpixel |
GlyphFormat::TransformedSubpixel => {
if text_cpu.font.bg_color.a != 0 {
- BlendMode::SubpixelWithBgColor
+ (
+ BlendMode::SubpixelWithBgColor,
+ ShaderColorMode::FromRenderPassMode,
+ )
} else if ctx.use_dual_source_blending {
- BlendMode::SubpixelDualSource
+ (
+ BlendMode::SubpixelDualSource,
+ ShaderColorMode::SubpixelDualSource,
+ )
} else {
- BlendMode::SubpixelConstantTextColor(text_cpu.font.color.into())
+ (
+ BlendMode::SubpixelConstantTextColor(text_cpu.font.color.into()),
+ ShaderColorMode::SubpixelConstantTextColor,
+ )
}
}
GlyphFormat::Alpha |
- GlyphFormat::TransformedAlpha |
- GlyphFormat::Bitmap |
- GlyphFormat::ColorBitmap => BlendMode::PremultipliedAlpha,
+ GlyphFormat::TransformedAlpha => {
+ (
+ BlendMode::PremultipliedAlpha,
+ ShaderColorMode::Alpha,
+ )
+ }
+ GlyphFormat::Bitmap => {
+ (
+ BlendMode::PremultipliedAlpha,
+ ShaderColorMode::Bitmap,
+ )
+ }
+ GlyphFormat::ColorBitmap => {
+ (
+ BlendMode::PremultipliedAlpha,
+ ShaderColorMode::ColorBitmap,
+ )
+ }
};
let key = BatchKey::new(kind, blend_mode, textures);
let batch = batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
for glyph in glyphs {
batch.push(base_instance.build(
glyph.index_in_text_run,
glyph.uv_rect_address.as_int(),
- subpx_dir as u32 as i32,
+ (subpx_dir as u32 as i32) << 16 |
+ (color_mode as u32 as i32),
));
}
},
);
}
}
}
@@ -1582,18 +1608,18 @@ pub fn resolve_image(
}
}
}
/// Construct a polygon from stacking context boundaries.
/// `anchor` here is an index that's going to be preserved in all the
/// splits of the polygon.
fn make_polygon(
- rect: LayerRect,
- transform: &LayerToWorldTransform,
+ rect: LayoutRect,
+ transform: &LayoutToWorldTransform,
anchor: usize,
) -> Polygon<f64, WorldPixel> {
let mat = TypedTransform3D::row_major(
transform.m11 as f64,
transform.m12 as f64,
transform.m13 as f64,
transform.m14 as f64,
transform.m21 as f64,
@@ -1615,18 +1641,18 @@ fn make_polygon(
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct ClipBatcher {
/// Rectangle draws fill up the rectangles with rounded corners.
pub rectangles: Vec<ClipMaskInstance>,
/// Image draws apply the image masking.
pub images: FastHashMap<SourceTexture, Vec<ClipMaskInstance>>,
- pub border_clears: Vec<ClipMaskInstance>,
- pub borders: Vec<ClipMaskInstance>,
+ pub border_clears: Vec<ClipMaskBorderCornerDotDash>,
+ pub borders: Vec<ClipMaskBorderCornerDotDash>,
pub box_shadows: FastHashMap<SourceTexture, Vec<ClipMaskInstance>>,
pub line_decorations: Vec<ClipMaskInstance>,
}
impl ClipBatcher {
pub fn new() -> Self {
ClipBatcher {
rectangles: Vec::new(),
@@ -1740,26 +1766,36 @@ impl ClipBatcher {
}
ClipSource::RoundedRectangle(..) => {
self.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
}
ClipSource::BorderCorner(ref source) => {
- self.border_clears.push(ClipMaskInstance {
- clip_data_address: gpu_address,
- segment: 0,
- ..instance
- });
- for clip_index in 0 .. source.actual_clip_count {
- self.borders.push(ClipMaskInstance {
+ let instance = ClipMaskBorderCornerDotDash {
+ clip_mask_instance: ClipMaskInstance {
clip_data_address: gpu_address,
- segment: 1 + clip_index as i32,
+ segment: 0,
..instance
+ },
+ dot_dash_data: [0.; 8],
+ };
+
+ self.border_clears.push(instance);
+
+ for data in source.dot_dash_data.iter() {
+ self.borders.push(ClipMaskBorderCornerDotDash {
+ clip_mask_instance: ClipMaskInstance {
+ // The shader understands segment=0 as the clear, so the
+ // segment here just needs to be non-zero.
+ segment: 1,
+ ..instance.clip_mask_instance
+ },
+ dot_dash_data: *data,
})
}
}
}
}
}
}
}
--- a/gfx/webrender/src/border.rs
+++ b/gfx/webrender/src/border.rs
@@ -1,14 +1,14 @@
/* 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 api::{BorderRadius, BorderSide, BorderStyle, BorderWidths, ClipMode, ColorF, LayerPoint};
-use api::{LayerPrimitiveInfo, LayerRect, LayerSize, NormalBorder, RepeatMode, TexelRect};
+use api::{BorderRadius, BorderSide, BorderStyle, BorderWidths, ClipMode, ColorF, LayoutPoint};
+use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, NormalBorder, RepeatMode, TexelRect};
use clip::ClipSource;
use ellipse::Ellipse;
use display_list_flattener::DisplayListFlattener;
use gpu_cache::GpuDataRequest;
use prim_store::{BorderPrimitiveCpu, BrushClipMaskKind, BrushSegment, BrushSegmentDescriptor};
use prim_store::{EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain};
use util::{lerp, pack_as_float};
@@ -37,70 +37,70 @@ enum BorderCorner {
#[derive(Clone, Debug, PartialEq)]
pub enum BorderCornerKind {
None,
Solid,
Clip(BorderCornerInstance),
Mask(
BorderCornerClipData,
- LayerSize,
- LayerSize,
+ LayoutSize,
+ LayoutSize,
BorderCornerClipKind,
),
}
impl BorderCornerKind {
fn new_mask(
kind: BorderCornerClipKind,
width0: f32,
width1: f32,
corner: BorderCorner,
- radius: LayerSize,
- border_rect: LayerRect,
+ radius: LayoutSize,
+ border_rect: LayoutRect,
) -> BorderCornerKind {
- let size = LayerSize::new(width0.max(radius.width), width1.max(radius.height));
+ let size = LayoutSize::new(width0.max(radius.width), width1.max(radius.height));
let (origin, clip_center) = match corner {
BorderCorner::TopLeft => {
let origin = border_rect.origin;
let clip_center = origin + size;
(origin, clip_center)
}
BorderCorner::TopRight => {
- let origin = LayerPoint::new(
+ let origin = LayoutPoint::new(
border_rect.origin.x + border_rect.size.width - size.width,
border_rect.origin.y,
);
- let clip_center = origin + LayerSize::new(0.0, size.height);
+ let clip_center = origin + LayoutSize::new(0.0, size.height);
(origin, clip_center)
}
BorderCorner::BottomRight => {
let origin = border_rect.origin + (border_rect.size - size);
let clip_center = origin;
(origin, clip_center)
}
BorderCorner::BottomLeft => {
- let origin = LayerPoint::new(
+ let origin = LayoutPoint::new(
border_rect.origin.x,
border_rect.origin.y + border_rect.size.height - size.height,
);
- let clip_center = origin + LayerSize::new(size.width, 0.0);
+ let clip_center = origin + LayoutSize::new(size.width, 0.0);
(origin, clip_center)
}
};
let clip_data = BorderCornerClipData {
- corner_rect: LayerRect::new(origin, size),
+ corner_rect: LayoutRect::new(origin, size),
clip_center,
corner: pack_as_float(corner as u32),
kind: pack_as_float(kind as u32),
};
- BorderCornerKind::Mask(clip_data, radius, LayerSize::new(width0, width1), kind)
+ BorderCornerKind::Mask(clip_data, radius, LayoutSize::new(width0, width1), kind)
}
- fn get_radius(&self, original_radius: &LayerSize) -> LayerSize {
+ fn get_radius(&self, original_radius: &LayoutSize) -> LayoutSize {
match *self {
BorderCornerKind::Solid => *original_radius,
BorderCornerKind::Clip(..) => *original_radius,
BorderCornerKind::Mask(_, ref radius, _, _) => *radius,
BorderCornerKind::None => *original_radius,
}
}
}
@@ -112,19 +112,19 @@ pub enum BorderEdgeKind {
Clip,
}
fn get_corner(
edge0: &BorderSide,
width0: f32,
edge1: &BorderSide,
width1: f32,
- radius: &LayerSize,
+ radius: &LayoutSize,
corner: BorderCorner,
- border_rect: &LayerRect,
+ border_rect: &LayoutRect,
) -> BorderCornerKind {
// If both widths are 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 {
@@ -231,17 +231,17 @@ fn get_edge(edge: &BorderSide, width: f3
BorderStyle::Ridge |
BorderStyle::Dashed |
BorderStyle::Dotted => (BorderEdgeKind::Clip, width),
}
}
pub fn ensure_no_corner_overlap(
radius: &mut BorderRadius,
- rect: &LayerRect,
+ rect: &LayoutRect,
) {
let mut ratio = 1.0;
let top_left_radius = &mut radius.top_left;
let top_right_radius = &mut radius.top_right;
let bottom_right_radius = &mut radius.bottom_right;
let bottom_left_radius = &mut radius.bottom_left;
let sum = top_left_radius.width + top_right_radius.width;
@@ -277,17 +277,17 @@ pub fn ensure_no_corner_overlap(
bottom_right_radius.width *= ratio;
bottom_right_radius.height *= ratio;
}
}
impl<'a> DisplayListFlattener<'a> {
fn add_normal_border_primitive(
&mut self,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
border: &NormalBorder,
radius: &BorderRadius,
widths: &BorderWidths,
clip_and_scroll: ScrollNodeAndClipChain,
corner_instances: [BorderCornerInstance; 4],
edges: [BorderEdgeKind; 4],
clip_sources: Vec<ClipSource>,
) {
@@ -345,17 +345,17 @@ impl<'a> DisplayListFlattener<'a> {
}
// 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_normal_border(
&mut self,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
border: &NormalBorder,
widths: &BorderWidths,
clip_and_scroll: ScrollNodeAndClipChain,
) {
// 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
@@ -382,40 +382,40 @@ impl<'a> DisplayListFlattener<'a> {
if is_simple_border {
let extra_clips = vec![
ClipSource::new_rounded_rect(
info.rect,
border.radius,
ClipMode::Clip,
),
ClipSource::new_rounded_rect(
- LayerRect::new(
- LayerPoint::new(
+ LayoutRect::new(
+ LayoutPoint::new(
info.rect.origin.x + widths.left,
info.rect.origin.y + widths.top,
),
- LayerSize::new(
+ LayoutSize::new(
info.rect.size.width - widths.left - widths.right,
info.rect.size.height - widths.top - widths.bottom,
),
),
BorderRadius {
- top_left: LayerSize::new(
+ top_left: LayoutSize::new(
(border.radius.top_left.width - widths.left).max(0.0),
(border.radius.top_left.height - widths.top).max(0.0),
),
- top_right: LayerSize::new(
+ top_right: LayoutSize::new(
(border.radius.top_right.width - widths.right).max(0.0),
(border.radius.top_right.height - widths.top).max(0.0),
),
- bottom_left: LayerSize::new(
+ bottom_left: LayoutSize::new(
(border.radius.bottom_left.width - widths.left).max(0.0),
(border.radius.bottom_left.height - widths.bottom).max(0.0),
),
- bottom_right: LayerSize::new(
+ bottom_right: LayoutSize::new(
(border.radius.bottom_right.width - widths.right).max(0.0),
(border.radius.bottom_right.height - widths.bottom).max(0.0),
),
},
ClipMode::ClipOut,
),
];
@@ -488,29 +488,29 @@ impl<'a> DisplayListFlattener<'a> {
let all_edges_simple = edges.iter().all(|e| {
*e == BorderEdgeKind::Solid || *e == BorderEdgeKind::None
});
let has_no_curve = radius.is_zero();
if has_no_curve && all_corners_simple && all_edges_simple {
let p0 = info.rect.origin;
- let p1 = LayerPoint::new(
+ let p1 = LayoutPoint::new(
info.rect.origin.x + left_len,
info.rect.origin.y + top_len,
);
- let p2 = LayerPoint::new(
+ let p2 = LayoutPoint::new(
info.rect.origin.x + info.rect.size.width - right_len,
info.rect.origin.y + info.rect.size.height - bottom_len,
);
let p3 = info.rect.bottom_right();
let segment = |x0, y0, x1, y1| BrushSegment::new(
- LayerPoint::new(x0, y0),
- LayerSize::new(x1-x0, y1-y0),
+ LayoutPoint::new(x0, y0),
+ LayoutSize::new(x1-x0, y1-y0),
true,
EdgeAaSegmentMask::all() // Note: this doesn't seem right, needs revision
);
// Add a solid rectangle for each visible edge/corner combination.
if top_edge == BorderEdgeKind::Solid {
let descriptor = BrushSegmentDescriptor {
segments: vec![
@@ -672,27 +672,27 @@ pub enum BorderCornerClipKind {
Dot,
}
/// The source data for a border corner clip mask.
#[derive(Debug, Clone)]
pub struct BorderCornerClipSource {
pub corner_data: BorderCornerClipData,
pub max_clip_count: usize,
- pub actual_clip_count: usize,
kind: BorderCornerClipKind,
- widths: LayerSize,
+ widths: LayoutSize,
ellipse: Ellipse,
+ pub dot_dash_data: Vec<[f32; 8]>,
}
impl BorderCornerClipSource {
pub fn new(
corner_data: BorderCornerClipData,
- corner_radius: LayerSize,
- widths: LayerSize,
+ corner_radius: LayoutSize,
+ widths: LayoutSize,
kind: BorderCornerClipKind,
) -> BorderCornerClipSource {
// Work out a dash length (and therefore dash count)
// based on the width of the border edges. The "correct"
// dash length is not mentioned in the CSS borders
// spec. The calculation below is similar, but not exactly
// the same as what Gecko uses.
// TODO(gw): Iterate on this to get it closer to what Gecko
@@ -748,55 +748,59 @@ impl BorderCornerClipSource {
}
}
};
BorderCornerClipSource {
kind,
corner_data,
max_clip_count,
- actual_clip_count: 0,
ellipse,
widths,
+ dot_dash_data: Vec::new(),
}
}
pub fn write(&mut self, mut request: GpuDataRequest) {
self.corner_data.write(&mut request);
+ assert_eq!(request.close(), 2);
match self.kind {
BorderCornerClipKind::Dash => {
// Get the correct dash arc length.
- self.actual_clip_count = self.max_clip_count;
let dash_arc_length =
- 0.5 * self.ellipse.total_arc_length / (self.actual_clip_count - 1) as f32;
+ 0.5 * self.ellipse.total_arc_length / (self.max_clip_count - 1) as f32;
+ self.dot_dash_data.clear();
let mut current_arc_length = -0.5 * dash_arc_length;
- for _ in 0 .. self.actual_clip_count {
+ for _ in 0 .. self.max_clip_count {
let arc_length0 = current_arc_length;
current_arc_length += dash_arc_length;
let arc_length1 = current_arc_length;
current_arc_length += dash_arc_length;
- let dash_data =
- BorderCornerDashClipData::new(arc_length0, arc_length1, &self.ellipse);
- dash_data.write(&mut request);
+ let alpha = self.ellipse.find_angle_for_arc_length(arc_length0);
+ let beta = self.ellipse.find_angle_for_arc_length(arc_length1);
+
+ let (point0, tangent0) = self.ellipse.get_point_and_tangent(alpha);
+ let (point1, tangent1) = self.ellipse.get_point_and_tangent(beta);
+
+ self.dot_dash_data.push([
+ point0.x, point0.y, tangent0.x, tangent0.y,
+ point1.x, point1.y, tangent1.x, tangent1.y
+ ]);
}
-
- assert_eq!(request.close(), 2 + 2 * self.actual_clip_count);
}
BorderCornerClipKind::Dot if self.max_clip_count == 1 => {
let dot_diameter = lerp(self.widths.width, self.widths.height, 0.5);
- let dot = BorderCornerDotClipData {
- center: LayerPoint::new(self.widths.width / 2.0, self.widths.height / 2.0),
- radius: 0.5 * dot_diameter,
- };
- self.actual_clip_count = 1;
- dot.write(&mut request);
- assert_eq!(request.close(), 3);
+ self.dot_dash_data.clear();
+ self.dot_dash_data.push([
+ self.widths.width / 2.0, self.widths.height / 2.0, 0.5 * dot_diameter, 0.,
+ 0., 0., 0., 0.,
+ ]);
}
BorderCornerClipKind::Dot => {
let mut forward_dots = Vec::new();
let mut back_dots = Vec::new();
let mut leftover_arc_length = 0.0;
// Alternate between adding dots at the start and end of the
// ellipse arc. This ensures that we always end up with an exact
@@ -847,55 +851,56 @@ impl BorderCornerClipSource {
back_dots.push(dot);
}
}
// Now step through the dots, and distribute any extra
// leftover space on the arc between them evenly. Once
// the final arc position is determined, generate the correct
// arc positions and angles that get passed to the clip shader.
- self.actual_clip_count = forward_dots.len() + back_dots.len();
- let extra_space_per_dot = leftover_arc_length / (self.actual_clip_count - 1) as f32;
+ let number_of_dots = forward_dots.len() + back_dots.len();
+ let extra_space_per_dot = leftover_arc_length / (number_of_dots - 1) as f32;
+
+ self.dot_dash_data.clear();
+
+ let create_dot_data = |ellipse: &Ellipse, arc_length: f32, radius: f32| -> [f32; 8] {
+ // Represents the GPU data for drawing a single dot to a clip mask. The order
+ // these are specified must stay in sync with the way this data is read in the
+ // dot clip shader.
+ let theta = ellipse.find_angle_for_arc_length(arc_length);
+ let (center, _) = ellipse.get_point_and_tangent(theta);
+ [center.x, center.y, radius, 0., 0., 0., 0., 0.,]
+ };
for (i, dot) in forward_dots.iter().enumerate() {
let extra_dist = i as f32 * extra_space_per_dot;
- let dot = BorderCornerDotClipData::new(
- dot.arc_pos + extra_dist,
- 0.5 * dot.diameter,
- &self.ellipse,
- );
- dot.write(&mut request);
+ let dot_data = create_dot_data(&self.ellipse, dot.arc_pos + extra_dist, 0.5 * dot.diameter);
+ self.dot_dash_data.push(dot_data);
}
for (i, dot) in back_dots.iter().enumerate() {
let extra_dist = i as f32 * extra_space_per_dot;
- let dot = BorderCornerDotClipData::new(
- dot.arc_pos - extra_dist,
- 0.5 * dot.diameter,
- &self.ellipse,
- );
- dot.write(&mut request);
+ let dot_data = create_dot_data(&self.ellipse, dot.arc_pos - extra_dist, 0.5 * dot.diameter);
+ self.dot_dash_data.push(dot_data);
}
-
- assert_eq!(request.close(), 2 + self.actual_clip_count);
}
}
}
}
/// Represents the common GPU data for writing a
/// clip mask for a border corner.
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
pub struct BorderCornerClipData {
/// Local space rect of the border corner.
- corner_rect: LayerRect,
+ corner_rect: LayoutRect,
/// Local space point that is the center of the
/// circle or ellipse that we are clipping against.
- clip_center: LayerPoint,
+ clip_center: LayoutPoint,
/// The shader needs to know which corner, to
/// be able to flip the dash tangents to the
/// right orientation.
corner: f32, // Of type BorderCorner enum
kind: f32, // Of type BorderCornerClipKind enum
}
impl BorderCornerClipData {
@@ -905,117 +910,49 @@ impl BorderCornerClipData {
self.clip_center.x,
self.clip_center.y,
self.corner,
self.kind,
]);
}
}
-/// Represents the GPU data for drawing a single dash
-/// to a clip mask. A dash clip is defined by two lines.
-/// We store a point on the ellipse curve, and a tangent
-/// to that point, which allows for efficient line-distance
-/// calculations in the fragment shader.
-#[derive(Debug, Clone)]
-#[repr(C)]
-pub struct BorderCornerDashClipData {
- pub point0: LayerPoint,
- pub tangent0: LayerPoint,
- pub point1: LayerPoint,
- pub tangent1: LayerPoint,
-}
-
-impl BorderCornerDashClipData {
- pub fn new(arc_length0: f32, arc_length1: f32, ellipse: &Ellipse) -> BorderCornerDashClipData {
- let alpha = ellipse.find_angle_for_arc_length(arc_length0);
- let beta = ellipse.find_angle_for_arc_length(arc_length1);
-
- let (p0, t0) = ellipse.get_point_and_tangent(alpha);
- let (p1, t1) = ellipse.get_point_and_tangent(beta);
-
- BorderCornerDashClipData {
- point0: p0,
- tangent0: t0,
- point1: p1,
- tangent1: t1,
- }
- }
-
- fn write(&self, request: &mut GpuDataRequest) {
- request.push([
- self.point0.x,
- self.point0.y,
- self.tangent0.x,
- self.tangent0.y,
- ]);
- request.push([
- self.point1.x,
- self.point1.y,
- self.tangent1.x,
- self.tangent1.y,
- ]);
- }
-}
-
-/// Represents the GPU data for drawing a single dot
-/// to a clip mask.
-#[derive(Debug, Clone)]
-#[repr(C)]
-pub struct BorderCornerDotClipData {
- pub center: LayerPoint,
- pub radius: f32,
-}
-
-impl BorderCornerDotClipData {
- pub fn new(arc_length: f32, radius: f32, ellipse: &Ellipse) -> BorderCornerDotClipData {
- let theta = ellipse.find_angle_for_arc_length(arc_length);
- let (center, _) = ellipse.get_point_and_tangent(theta);
-
- BorderCornerDotClipData { center, radius }
- }
-
- fn write(&self, request: &mut GpuDataRequest) {
- request.push([self.center.x, self.center.y, self.radius, 0.0]);
- }
-}
-
#[derive(Copy, Clone, Debug)]
struct DotInfo {
arc_pos: f32,
diameter: f32,
}
impl DotInfo {
fn new(arc_pos: f32, diameter: f32) -> DotInfo {
DotInfo { arc_pos, diameter }
}
}
#[derive(Debug, Clone)]
pub struct ImageBorderSegment {
- pub geom_rect: LayerRect,
+ pub geom_rect: LayoutRect,
pub sub_rect: TexelRect,
- pub stretch_size: LayerSize,
- pub tile_spacing: LayerSize,
+ pub stretch_size: LayoutSize,
+ pub tile_spacing: LayoutSize,
}
impl ImageBorderSegment {
pub fn new(
- rect: LayerRect,
+ rect: LayoutRect,
sub_rect: TexelRect,
repeat_horizontal: RepeatMode,
repeat_vertical: RepeatMode,
) -> ImageBorderSegment {
- let tile_spacing = LayerSize::zero();
+ let tile_spacing = LayoutSize::zero();
debug_assert!(sub_rect.uv1.x >= sub_rect.uv0.x);
debug_assert!(sub_rect.uv1.y >= sub_rect.uv0.y);
- let image_size = LayerSize::new(
+ let image_size = LayoutSize::new(
sub_rect.uv1.x - sub_rect.uv0.x,
sub_rect.uv1.y - sub_rect.uv0.y,
);
let stretch_size_x = match repeat_horizontal {
RepeatMode::Stretch => rect.size.width,
RepeatMode::Repeat => image_size.width,
RepeatMode::Round | RepeatMode::Space => {
@@ -1031,13 +968,13 @@ impl ImageBorderSegment {
error!("Round/Space not supported yet!");
rect.size.height
}
};
ImageBorderSegment {
geom_rect: rect,
sub_rect,
- stretch_size: LayerSize::new(stretch_size_x, stretch_size_y),
+ stretch_size: LayoutSize::new(stretch_size_x, stretch_size_y),
tile_spacing,
}
}
}
--- a/gfx/webrender/src/box_shadow.rs
+++ b/gfx/webrender/src/box_shadow.rs
@@ -1,14 +1,14 @@
/* 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 api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, DeviceIntSize, LayerPrimitiveInfo};
-use api::{LayerRect, LayerSize, LayerVector2D, LayoutSize};
+use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, DeviceIntSize, LayoutPrimitiveInfo};
+use api::{LayoutRect, LayoutSize, LayoutVector2D};
use clip::ClipSource;
use display_list_flattener::DisplayListFlattener;
use gpu_cache::GpuCacheHandle;
use gpu_types::BoxShadowStretchMode;
use prim_store::{BrushKind, BrushPrimitive, PrimitiveContainer};
use prim_store::ScrollNodeAndClipChain;
use render_task::RenderTaskCacheEntryHandle;
use util::RectHelpers;
@@ -24,25 +24,25 @@ pub struct BoxShadowClipSource {
// The current cache key (in device-pixels), and handles
// to the cached clip region and blurred texture.
pub cache_key: Option<(DeviceIntSize, BoxShadowCacheKey)>,
pub cache_handle: Option<RenderTaskCacheEntryHandle>,
pub clip_data_handle: GpuCacheHandle,
// Local-space size of the required render task size.
- pub shadow_rect_alloc_size: LayerSize,
+ pub shadow_rect_alloc_size: LayoutSize,
// The minimal shadow rect for the parameters above,
// used when drawing the shadow rect to be blurred.
- pub minimal_shadow_rect: LayerRect,
+ pub minimal_shadow_rect: LayoutRect,
// Local space rect for the shadow to be drawn or
// stretched in the shadow primitive.
- pub prim_shadow_rect: LayerRect,
+ pub prim_shadow_rect: LayoutRect,
}
// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
pub const BLUR_SAMPLE_SCALE: f32 = 3.0;
// Maximum blur radius.
// Taken from https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/layout/painting/nsCSSRendering.cpp#4412
pub const MAX_BLUR_RADIUS : f32 = 300.;
@@ -62,18 +62,18 @@ pub struct BoxShadowCacheKey {
pub br_bottom_right: DeviceIntSize,
pub br_bottom_left: DeviceIntSize,
}
impl<'a> DisplayListFlattener<'a> {
pub fn add_box_shadow(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- prim_info: &LayerPrimitiveInfo,
- box_offset: &LayerVector2D,
+ prim_info: &LayoutPrimitiveInfo,
+ box_offset: &LayoutVector2D,
color: &ColorF,
mut blur_radius: f32,
spread_radius: f32,
border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
if color.a == 0.0 {
return;
@@ -142,22 +142,21 @@ impl<'a> DisplayListFlattener<'a> {
(prim_info.rect, border_radius)
}
};
clips.push(ClipSource::new_rounded_rect(final_prim_rect, clip_radius, ClipMode::Clip));
self.add_primitive(
clip_and_scroll,
- &LayerPrimitiveInfo::with_clip_rect(final_prim_rect, prim_info.clip_rect),
+ &LayoutPrimitiveInfo::with_clip_rect(final_prim_rect, prim_info.clip_rect),
clips,
PrimitiveContainer::Brush(
- BrushPrimitive::new(BrushKind::Solid {
- color: *color,
- },
+ BrushPrimitive::new(
+ BrushKind::new_solid(*color),
None,
)
),
);
} else {
// Normal path for box-shadows with a valid blur radius.
let blur_offset = BLUR_SAMPLE_SCALE * blur_radius;
let mut extra_clips = vec![];
@@ -172,19 +171,17 @@ impl<'a> DisplayListFlattener<'a> {
// Get the local rect of where the shadow will be drawn,
// expanded to include room for the blurred region.
let dest_rect = shadow_rect.inflate(blur_offset, blur_offset);
// Draw the box-shadow as a solid rect, using a box-shadow
// clip mask source.
let prim = BrushPrimitive::new(
- BrushKind::Solid {
- color: *color,
- },
+ BrushKind::new_solid(*color),
None,
);
// Create the box-shadow clip source.
let shadow_clip_source = ClipSource::new_box_shadow(
shadow_rect,
shadow_radius,
dest_rect,
@@ -199,17 +196,17 @@ impl<'a> DisplayListFlattener<'a> {
return;
}
// Add the box-shadow clip source.
extra_clips.push(shadow_clip_source);
// Outset shadows are expanded by the shadow
// region from the original primitive.
- LayerPrimitiveInfo::with_clip_rect(dest_rect, prim_info.clip_rect)
+ LayoutPrimitiveInfo::with_clip_rect(dest_rect, prim_info.clip_rect)
}
BoxShadowClipMode::Inset => {
// If the inner shadow rect contains the prim
// rect, no pixels will be shadowed.
if border_radius.is_zero() &&
shadow_rect.inflate(-blur_radius, -blur_radius).contains_rect(&prim_info.rect) {
return;
}
--- a/gfx/webrender/src/clip.rs
+++ b/gfx/webrender/src/clip.rs
@@ -1,54 +1,54 @@
/* 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 api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
-use api::{ImageRendering, LayerRect, LayerSize, LayoutPoint, LayoutVector2D, LocalClip};
-use api::{BoxShadowClipMode, LayerPoint, LayerToWorldScale, LineOrientation, LineStyle};
+use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D, LocalClip};
+use api::{BoxShadowClipMode, LayoutToWorldScale, LineOrientation, LineStyle};
use border::{BorderCornerClipSource, ensure_no_corner_overlap};
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
use ellipse::Ellipse;
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use gpu_types::{BoxShadowStretchMode, ClipScrollNodeIndex};
use prim_store::{ClipData, ImageMaskData};
use render_task::to_cache_size;
use resource_cache::{ImageRequest, ResourceCache};
-use util::{LayerToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
+use util::{LayoutToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
use util::{extract_inner_rect_safe, pack_as_float};
use std::sync::Arc;
#[derive(Debug)]
pub enum ClipStoreMarker {}
pub type ClipStore = FreeList<ClipSources, ClipStoreMarker>;
pub type ClipSourcesHandle = FreeListHandle<ClipStoreMarker>;
pub type ClipSourcesWeakHandle = WeakFreeListHandle<ClipStoreMarker>;
#[derive(Debug)]
pub struct LineDecorationClipSource {
- rect: LayerRect,
+ rect: LayoutRect,
style: LineStyle,
orientation: LineOrientation,
wavy_line_thickness: f32,
}
#[derive(Clone, Debug)]
pub struct ClipRegion {
- pub main: LayerRect,
+ pub main: LayoutRect,
pub image_mask: Option<ImageMask>,
pub complex_clips: Vec<ComplexClipRegion>,
}
impl ClipRegion {
pub fn create_for_clip_node(
- rect: LayerRect,
+ rect: LayoutRect,
mut complex_clips: Vec<ComplexClipRegion>,
mut image_mask: Option<ImageMask>,
reference_frame_relative_offset: &LayoutVector2D,
) -> ClipRegion {
let rect = rect.translate(reference_frame_relative_offset);
if let Some(ref mut image_mask) = image_mask {
image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset);
@@ -79,18 +79,18 @@ impl ClipRegion {
None,
reference_frame_relative_offset
)
}
}
#[derive(Debug)]
pub enum ClipSource {
- Rectangle(LayerRect, ClipMode),
- RoundedRectangle(LayerRect, BorderRadius, ClipMode),
+ Rectangle(LayoutRect, ClipMode),
+ RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
Image(ImageMask),
/// TODO(gw): This currently only handles dashed style
/// clips, where the border style is dashed for both
/// adjacent border edges. Expand to handle dotted style
/// and different styles per edge.
BorderCorner(BorderCornerClipSource),
BoxShadow(BoxShadowClipSource),
LineDecoration(LineDecorationClipSource),
@@ -115,62 +115,62 @@ impl From<ClipRegion> for ClipSources {
}
ClipSources::new(clips)
}
}
impl ClipSource {
pub fn new_rounded_rect(
- rect: LayerRect,
+ rect: LayoutRect,
mut radii: BorderRadius,
clip_mode: ClipMode
) -> ClipSource {
if radii.is_zero() {
ClipSource::Rectangle(rect, clip_mode)
} else {
ensure_no_corner_overlap(&mut radii, &rect);
ClipSource::RoundedRectangle(
rect,
radii,
clip_mode,
)
}
}
pub fn new_line_decoration(
- rect: LayerRect,
+ rect: LayoutRect,
style: LineStyle,
orientation: LineOrientation,
wavy_line_thickness: f32,
) -> ClipSource {
ClipSource::LineDecoration(
LineDecorationClipSource {
rect,
style,
orientation,
wavy_line_thickness,
}
)
}
pub fn new_box_shadow(
- shadow_rect: LayerRect,
+ shadow_rect: LayoutRect,
shadow_radius: BorderRadius,
- prim_shadow_rect: LayerRect,
+ prim_shadow_rect: LayoutRect,
blur_radius: f32,
clip_mode: BoxShadowClipMode,
) -> ClipSource {
// Get the fractional offsets required to match the
// source rect with a minimal rect.
- let fract_offset = LayerPoint::new(
+ let fract_offset = LayoutPoint::new(
shadow_rect.origin.x.fract().abs(),
shadow_rect.origin.y.fract().abs(),
);
- let fract_size = LayerSize::new(
+ let fract_size = LayoutSize::new(
shadow_rect.size.width.fract().abs(),
shadow_rect.size.height.fract().abs(),
);
// Create a minimal size primitive mask to blur. In this
// case, we ensure the size of each corner is the same,
// to simplify the shader logic that stretches the blurred
// result across the primitive.
@@ -187,28 +187,28 @@ impl ClipSource {
let blur_region = (BLUR_SAMPLE_SCALE * blur_radius).ceil();
// If the largest corner is smaller than the blur radius, we need to ensure
// that it's big enough that the corners don't affect the middle segments.
let used_corner_width = max_corner_width.max(blur_region);
let used_corner_height = max_corner_height.max(blur_region);
// Minimal nine-patch size, corner + internal + corner.
- let min_shadow_rect_size = LayerSize::new(
+ let min_shadow_rect_size = LayoutSize::new(
2.0 * used_corner_width + blur_region,
2.0 * used_corner_height + blur_region,
);
// The minimal rect to blur.
- let mut minimal_shadow_rect = LayerRect::new(
- LayerPoint::new(
+ let mut minimal_shadow_rect = LayoutRect::new(
+ LayoutPoint::new(
blur_region + fract_offset.x,
blur_region + fract_offset.y,
),
- LayerSize::new(
+ LayoutSize::new(
min_shadow_rect_size.width + fract_size.width,
min_shadow_rect_size.height + fract_size.height,
),
);
// If the width or height ends up being bigger than the original
// primitive shadow rect, just blur the entire rect along that
// axis and draw that as a simple blit. This is necessary for
@@ -222,17 +222,17 @@ impl ClipSource {
let mut stretch_mode_y = BoxShadowStretchMode::Stretch;
if shadow_rect.size.height < minimal_shadow_rect.size.height {
minimal_shadow_rect.size.height = shadow_rect.size.height;
stretch_mode_y = BoxShadowStretchMode::Simple;
}
// Expand the shadow rect by enough room for the blur to take effect.
- let shadow_rect_alloc_size = LayerSize::new(
+ let shadow_rect_alloc_size = LayoutSize::new(
2.0 * blur_region + minimal_shadow_rect.size.width.ceil(),
2.0 * blur_region + minimal_shadow_rect.size.height.ceil(),
);
ClipSource::BoxShadow(BoxShadowClipSource {
shadow_rect_alloc_size,
shadow_radius,
prim_shadow_rect,
@@ -262,18 +262,18 @@ impl ClipSource {
}
}
}
}
#[derive(Debug)]
pub struct ClipSources {
pub clips: Vec<(ClipSource, GpuCacheHandle)>,
- pub local_inner_rect: LayerRect,
- pub local_outer_rect: Option<LayerRect>
+ pub local_inner_rect: LayoutRect,
+ pub local_outer_rect: Option<LayoutRect>
}
impl ClipSources {
pub fn new(clips: Vec<ClipSource>) -> ClipSources {
let (local_inner_rect, local_outer_rect) = Self::calculate_inner_and_outer_rects(&clips);
let clips = clips
.into_iter()
@@ -286,26 +286,26 @@ impl ClipSources {
local_outer_rect,
}
}
pub fn clips(&self) -> &[(ClipSource, GpuCacheHandle)] {
&self.clips
}
- fn calculate_inner_and_outer_rects(clips: &Vec<ClipSource>) -> (LayerRect, Option<LayerRect>) {
+ fn calculate_inner_and_outer_rects(clips: &Vec<ClipSource>) -> (LayoutRect, Option<LayoutRect>) {
if clips.is_empty() {
- return (LayerRect::zero(), None);
+ 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(LayerRect::max_rect());
+ 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;
@@ -345,25 +345,25 @@ impl ClipSources {
ClipSource::LineDecoration(..) => {
can_calculate_inner_rect = false;
break;
}
}
}
let outer = if can_calculate_outer_rect {
- Some(local_outer.unwrap_or_else(LayerRect::zero))
+ Some(local_outer.unwrap_or_else(LayoutRect::zero))
} else {
None
};
let inner = if can_calculate_inner_rect {
- local_inner.unwrap_or_else(LayerRect::zero)
+ local_inner.unwrap_or_else(LayoutRect::zero)
} else {
- LayerRect::zero()
+ LayoutRect::zero()
};
(inner, outer)
}
pub fn update(
&mut self,
gpu_cache: &mut GpuCache,
@@ -428,17 +428,17 @@ impl ClipSources {
}
ClipSource::BoxShadow(ref mut info) => {
// Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
// "the image that would be generated by applying to the shadow a
// Gaussian blur with a standard deviation equal to half the blur radius."
let blur_radius_dp = (info.blur_radius * 0.5 * device_pixel_scale.0).round();
// Create the cache key for this box-shadow render task.
- let content_scale = LayerToWorldScale::new(1.0) * device_pixel_scale;
+ let content_scale = LayoutToWorldScale::new(1.0) * device_pixel_scale;
let cache_size = to_cache_size(info.shadow_rect_alloc_size * content_scale);
let bs_cache_key = BoxShadowCacheKey {
blur_radius_dp: blur_radius_dp as i32,
clip_mode: info.clip_mode,
rect_size: (info.shadow_rect_alloc_size * content_scale).round().to_i32(),
br_top_left: (info.shadow_radius.top_left * content_scale).round().to_i32(),
br_top_right: (info.shadow_radius.top_right * content_scale).round().to_i32(),
br_bottom_right: (info.shadow_radius.bottom_right * content_scale).round().to_i32(),
@@ -459,17 +459,17 @@ impl ClipSources {
}
_ => {}
}
}
}
pub fn get_screen_bounds(
&self,
- transform: &LayerToWorldFastTransform,
+ transform: &LayoutToWorldFastTransform,
device_pixel_scale: DevicePixelScale,
) -> (DeviceIntRect, Option<DeviceIntRect>) {
// If this translation isn't axis aligned or has a perspective component, don't try to
// calculate the inner rectangle. The rectangle that we produce would include potentially
// clipped screen area.
// TODO(mrobinson): We should eventually try to calculate an inner region or some inner
// rectangle so that we can do screen inner rectangle optimizations for these kind of
// cilps.
@@ -488,32 +488,32 @@ impl ClipSources {
(screen_inner_rect, screen_outer_rect)
}
}
/// Represents a local rect and a device space
/// rectangles that are either outside or inside bounds.
#[derive(Clone, Debug, PartialEq)]
pub struct Geometry {
- pub local_rect: LayerRect,
+ pub local_rect: LayoutRect,
pub device_rect: DeviceIntRect,
}
-impl From<LayerRect> for Geometry {
- fn from(local_rect: LayerRect) -> Self {
+impl From<LayoutRect> for Geometry {
+ fn from(local_rect: LayoutRect) -> Self {
Geometry {
local_rect,
device_rect: DeviceIntRect::zero(),
}
}
}
pub fn rounded_rectangle_contains_point(
point: &LayoutPoint,
- rect: &LayerRect,
+ rect: &LayoutRect,
radii: &BorderRadius
) -> bool {
if !rect.contains(point) {
return false;
}
let top_left_center = rect.origin + radii.top_left.to_vector();
if top_left_center.x > point.x && top_left_center.y > point.y &&
@@ -544,17 +544,17 @@ pub fn rounded_rectangle_contains_point(
true
}
pub type ClipChainNodeRef = Option<Arc<ClipChainNode>>;
#[derive(Debug, Clone)]
pub struct ClipChainNode {
pub work_item: ClipWorkItem,
- pub local_clip_rect: LayerRect,
+ pub local_clip_rect: LayoutRect,
pub screen_outer_rect: DeviceIntRect,
pub screen_inner_rect: DeviceIntRect,
pub prev: ClipChainNodeRef,
}
#[derive(Debug, Clone)]
pub struct ClipChain {
pub parent_index: Option<ClipChainIndex>,
--- a/gfx/webrender/src/clip_scroll_node.rs
+++ b/gfx/webrender/src/clip_scroll_node.rs
@@ -1,50 +1,50 @@
/* 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 api::{DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect, LayerSize};
-use api::{LayerVector2D, LayoutTransform, LayoutVector2D, PipelineId, PropertyBinding};
+use api::{DevicePixelScale, ExternalScrollId, LayoutPixel, LayoutPoint, LayoutRect, LayoutSize};
+use api::{LayoutVector2D, LayoutTransform, PipelineId, PropertyBinding};
use api::{ScrollClamping, ScrollLocation, ScrollSensitivity, StickyOffsetBounds};
use api::WorldPoint;
use clip::{ClipChain, ClipChainNode, ClipSourcesHandle, ClipStore, ClipWorkItem};
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, CoordinateSystemId};
use clip_scroll_tree::TransformUpdateState;
use euclid::SideOffsets2D;
use geometry::ray_intersects_rect;
use gpu_cache::GpuCache;
use gpu_types::{ClipScrollNodeIndex as GPUClipScrollNodeIndex, ClipScrollNodeData};
use resource_cache::ResourceCache;
use scene::SceneProperties;
-use util::{LayerToWorldFastTransform, LayerFastTransform, LayoutFastTransform};
+use util::{LayoutToWorldFastTransform, LayoutFastTransform};
use util::{TransformedRectKind};
#[derive(Debug)]
pub struct StickyFrameInfo {
pub margins: SideOffsets2D<Option<f32>>,
pub vertical_offset_bounds: StickyOffsetBounds,
pub horizontal_offset_bounds: StickyOffsetBounds,
pub previously_applied_offset: LayoutVector2D,
- pub current_offset: LayerVector2D,
+ pub current_offset: LayoutVector2D,
}
impl StickyFrameInfo {
pub fn new(
margins: SideOffsets2D<Option<f32>>,
vertical_offset_bounds: StickyOffsetBounds,
horizontal_offset_bounds: StickyOffsetBounds,
previously_applied_offset: LayoutVector2D
) -> StickyFrameInfo {
StickyFrameInfo {
margins,
vertical_offset_bounds,
horizontal_offset_bounds,
previously_applied_offset,
- current_offset: LayerVector2D::zero(),
+ current_offset: LayoutVector2D::zero(),
}
}
}
#[derive(Debug)]
pub enum NodeType {
/// A reference frame establishes a new coordinate space in the tree.
ReferenceFrame(ReferenceFrameInfo),
@@ -84,27 +84,27 @@ impl NodeType {
}
}
}
/// Contains information common among all types of ClipScrollTree nodes.
#[derive(Debug)]
pub struct ClipScrollNode {
/// Viewing rectangle in the coordinate system of the parent reference frame.
- pub local_viewport_rect: LayerRect,
+ pub local_viewport_rect: LayoutRect,
/// The transformation for this viewport in world coordinates is the transformation for
/// our parent reference frame, plus any accumulated scrolling offsets from nodes
/// between our reference frame and this node. For reference frames, we also include
/// whatever local transformation this reference frame provides. This can be combined
/// with the local_viewport_rect to get its position in world space.
- pub world_viewport_transform: LayerToWorldFastTransform,
+ pub world_viewport_transform: LayoutToWorldFastTransform,
/// World transform for content transformed by this node.
- pub world_content_transform: LayerToWorldFastTransform,
+ pub world_content_transform: LayoutToWorldFastTransform,
/// Pipeline that this layer belongs to
pub pipeline_id: PipelineId,
/// Parent layer. If this is None, we are the root node.
pub parent: Option<ClipScrollNodeIndex>,
/// Child layers
@@ -119,93 +119,93 @@ pub struct ClipScrollNode {
pub invertible: bool,
/// The axis-aligned coordinate system id of this node.
pub coordinate_system_id: CoordinateSystemId,
/// 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: LayerFastTransform,
+ pub coordinate_system_relative_transform: LayoutFastTransform,
/// A linear ID / index of this clip-scroll node. Used as a reference to
/// pass to shaders, to allow them to fetch a given clip-scroll node.
pub node_data_index: GPUClipScrollNodeIndex,
}
impl ClipScrollNode {
pub fn new(
pipeline_id: PipelineId,
parent_index: Option<ClipScrollNodeIndex>,
- rect: &LayerRect,
+ rect: &LayoutRect,
node_type: NodeType
) -> Self {
ClipScrollNode {
local_viewport_rect: *rect,
- world_viewport_transform: LayerToWorldFastTransform::identity(),
- world_content_transform: LayerToWorldFastTransform::identity(),
+ world_viewport_transform: LayoutToWorldFastTransform::identity(),
+ world_content_transform: LayoutToWorldFastTransform::identity(),
parent: parent_index,
children: Vec::new(),
pipeline_id,
- node_type: node_type,
+ node_type,
invertible: true,
coordinate_system_id: CoordinateSystemId(0),
- coordinate_system_relative_transform: LayerFastTransform::identity(),
+ coordinate_system_relative_transform: LayoutFastTransform::identity(),
node_data_index: GPUClipScrollNodeIndex(0),
}
}
pub fn empty() -> ClipScrollNode {
- ClipScrollNode::new(PipelineId::dummy(), None, &LayerRect::zero(), NodeType::Empty)
+ ClipScrollNode::new(PipelineId::dummy(), None, &LayoutRect::zero(), NodeType::Empty)
}
pub fn new_scroll_frame(
pipeline_id: PipelineId,
parent_index: ClipScrollNodeIndex,
external_id: Option<ExternalScrollId>,
- frame_rect: &LayerRect,
- content_size: &LayerSize,
+ frame_rect: &LayoutRect,
+ content_size: &LayoutSize,
scroll_sensitivity: ScrollSensitivity,
) -> Self {
let node_type = NodeType::ScrollFrame(ScrollFrameInfo::new(
scroll_sensitivity,
- LayerSize::new(
+ LayoutSize::new(
(content_size.width - frame_rect.size.width).max(0.0),
(content_size.height - frame_rect.size.height).max(0.0)
),
external_id,
));
Self::new(pipeline_id, Some(parent_index), frame_rect, node_type)
}
pub fn new_reference_frame(
parent_index: Option<ClipScrollNodeIndex>,
- frame_rect: &LayerRect,
+ frame_rect: &LayoutRect,
source_transform: Option<PropertyBinding<LayoutTransform>>,
source_perspective: Option<LayoutTransform>,
- origin_in_parent_reference_frame: LayerVector2D,
+ origin_in_parent_reference_frame: LayoutVector2D,
pipeline_id: PipelineId,
) -> Self {
let identity = LayoutTransform::identity();
let source_perspective = source_perspective.map_or_else(
LayoutFastTransform::identity, |perspective| perspective.into());
let info = ReferenceFrameInfo {
- resolved_transform: LayerFastTransform::identity(),
+ resolved_transform: LayoutFastTransform::identity(),
source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)),
- source_perspective: source_perspective,
+ source_perspective,
origin_in_parent_reference_frame,
invertible: true,
};
Self::new(pipeline_id, parent_index, frame_rect, NodeType::ReferenceFrame(info))
}
pub fn new_sticky_frame(
parent_index: ClipScrollNodeIndex,
- frame_rect: LayerRect,
+ frame_rect: LayoutRect,
sticky_frame_info: StickyFrameInfo,
pipeline_id: PipelineId,
) -> Self {
let node_type = NodeType::StickyFrame(sticky_frame_info);
Self::new(pipeline_id, Some(parent_index), &frame_rect, node_type)
}
@@ -217,24 +217,24 @@ impl ClipScrollNode {
match self.node_type {
NodeType::ScrollFrame(ref mut scrolling) => {
let scroll_sensitivity = scrolling.scroll_sensitivity;
let scrollable_size = scrolling.scrollable_size;
*scrolling = *old_scrolling_state;
scrolling.scroll_sensitivity = scroll_sensitivity;
scrolling.scrollable_size = scrollable_size;
}
- _ if old_scrolling_state.offset != LayerVector2D::zero() => {
+ _ if old_scrolling_state.offset != LayoutVector2D::zero() => {
warn!("Tried to scroll a non-scroll node.")
}
_ => {}
}
}
- pub fn set_scroll_origin(&mut self, origin: &LayerPoint, clamp: ScrollClamping) -> bool {
+ pub fn set_scroll_origin(&mut self, origin: &LayoutPoint, clamp: ScrollClamping) -> bool {
let scrollable_size = self.scrollable_size();
let scrollable_width = scrollable_size.width;
let scrollable_height = scrollable_size.height;
let scrolling = match self.node_type {
NodeType::ScrollFrame(ref mut scrolling) => scrolling,
_ => {
warn!("Tried to scroll a non-scroll node.");
@@ -243,37 +243,37 @@ impl ClipScrollNode {
};
let new_offset = match clamp {
ScrollClamping::ToContentBounds => {
if scrollable_height <= 0. && scrollable_width <= 0. {
return false;
}
- let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0));
- LayerVector2D::new(
+ let origin = LayoutPoint::new(origin.x.max(0.0), origin.y.max(0.0));
+ LayoutVector2D::new(
(-origin.x).max(-scrollable_width).min(0.0).round(),
(-origin.y).max(-scrollable_height).min(0.0).round(),
)
}
- ScrollClamping::NoClamping => LayerPoint::zero() - *origin,
+ ScrollClamping::NoClamping => LayoutPoint::zero() - *origin,
};
if new_offset == scrolling.offset {
return false;
}
scrolling.offset = new_offset;
true
}
pub fn mark_uninvertible(&mut self) {
self.invertible = false;
- self.world_content_transform = LayerToWorldFastTransform::identity();
- self.world_viewport_transform = LayerToWorldFastTransform::identity();
+ self.world_content_transform = LayoutToWorldFastTransform::identity();
+ self.world_viewport_transform = LayoutToWorldFastTransform::identity();
}
pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) {
if !self.invertible {
node_data.push(ClipScrollNodeData::invalid());
return;
}
@@ -419,26 +419,26 @@ impl ClipScrollNode {
&state.nearest_scrolling_ancestor_offset,
&state.nearest_scrolling_ancestor_viewport,
);
// The transformation for the bounds of our viewport is the parent reference frame
// transform, plus any accumulated scroll offset from our parents, plus any offset
// provided by our own sticky positioning.
let accumulated_offset = state.parent_accumulated_scroll_offset + sticky_offset;
- self.world_viewport_transform = if accumulated_offset != LayerVector2D::zero() {
+ self.world_viewport_transform = if accumulated_offset != LayoutVector2D::zero() {
state.parent_reference_frame_transform.pre_translate(&accumulated_offset)
} else {
state.parent_reference_frame_transform
};
// The transformation for any content inside of us is the viewport transformation, plus
// whatever scrolling offset we supply as well.
let scroll_offset = self.scroll_offset();
- self.world_content_transform = if scroll_offset != LayerVector2D::zero() {
+ self.world_content_transform = if scroll_offset != LayoutVector2D::zero() {
self.world_viewport_transform.pre_translate(&scroll_offset)
} else {
self.world_viewport_transform
};
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);
@@ -460,75 +460,75 @@ impl ClipScrollNode {
let info = match self.node_type {
NodeType::ReferenceFrame(ref mut info) => info,
_ => unreachable!("Called update_transform_for_reference_frame on non-ReferenceFrame"),
};
// Resolve the transform against any property bindings.
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
info.resolved_transform =
- LayerFastTransform::with_vector(info.origin_in_parent_reference_frame)
+ LayoutFastTransform::with_vector(info.origin_in_parent_reference_frame)
.pre_mul(&source_transform.into())
.pre_mul(&info.source_perspective);
// The transformation for this viewport in world coordinates is the transformation for
// our parent reference frame, plus any accumulated scrolling offsets from nodes
// between our reference frame and this node. Finally, we also include
// whatever local transformation this reference frame provides. This can be combined
// with the local_viewport_rect to get its position in world space.
let relative_transform = info.resolved_transform
.post_translate(state.parent_accumulated_scroll_offset)
.to_transform()
- .with_destination::<LayerPixel>();
+ .with_destination::<LayoutPixel>();
self.world_viewport_transform =
state.parent_reference_frame_transform.pre_mul(&relative_transform.into());
self.world_content_transform = self.world_viewport_transform;
info.invertible = self.world_viewport_transform.is_invertible();
if !info.invertible {
return;
}
// 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 = LayerFastTransform::identity();
+ self.coordinate_system_relative_transform = LayoutFastTransform::identity();
state.current_coordinate_system_id = *next_coordinate_system_id;
next_coordinate_system_id.advance();
}
}
self.coordinate_system_id = state.current_coordinate_system_id;
}
fn calculate_sticky_offset(
&self,
- viewport_scroll_offset: &LayerVector2D,
- viewport_rect: &LayerRect,
- ) -> LayerVector2D {
+ viewport_scroll_offset: &LayoutVector2D,
+ viewport_rect: &LayoutRect,
+ ) -> LayoutVector2D {
let info = match self.node_type {
NodeType::StickyFrame(ref info) => info,
- _ => return LayerVector2D::zero(),
+ _ => return LayoutVector2D::zero(),
};
if info.margins.top.is_none() && info.margins.bottom.is_none() &&
info.margins.left.is_none() && info.margins.right.is_none() {
- return LayerVector2D::zero();
+ return LayoutVector2D::zero();
}
// The viewport and margins of the item establishes the maximum amount that it can
// be offset in order to keep it on screen. Since we care about the relationship
// between the scrolled content and unscrolled viewport we adjust the viewport's
// position by the scroll offset in order to work with their relative positions on the
// page.
let sticky_rect = self.local_viewport_rect.translate(viewport_scroll_offset);
- let mut sticky_offset = LayerVector2D::zero();
+ let mut sticky_offset = LayoutVector2D::zero();
if let Some(margin) = info.margins.top {
let top_viewport_edge = viewport_rect.min_y() + margin;
if sticky_rect.min_y() < top_viewport_edge {
// If the sticky rect is positioned above the top edge of the viewport (plus margin)
// we move it down so that it is fully inside the viewport.
sticky_offset.y = top_viewport_edge - sticky_rect.min_y();
} else if info.previously_applied_offset.y > 0.0 &&
sticky_rect.min_y() > top_viewport_edge {
@@ -618,17 +618,17 @@ impl ClipScrollNode {
// The transformation we are passing is the transformation of the parent
// reference frame and the offset is the accumulated offset of all the nodes
// between us and the parent reference frame. If we are a reference frame,
// we need to reset both these values.
match self.node_type {
NodeType::ReferenceFrame(ref info) => {
state.parent_reference_frame_transform = self.world_viewport_transform;
- state.parent_accumulated_scroll_offset = LayerVector2D::zero();
+ state.parent_accumulated_scroll_offset = LayoutVector2D::zero();
state.coordinate_system_relative_transform =
self.coordinate_system_relative_transform.clone();
let translation = -info.origin_in_parent_reference_frame;
state.nearest_scrolling_ancestor_viewport =
state.nearest_scrolling_ancestor_viewport
.translate(&translation);
}
NodeType::Clip{ .. } => { }
@@ -644,20 +644,20 @@ impl ClipScrollNode {
// only apply to contents inside the node.
state.parent_accumulated_scroll_offset =
info.current_offset + state.parent_accumulated_scroll_offset;
}
NodeType::Empty => unreachable!("Empty node remaining in ClipScrollTree."),
}
}
- pub fn scrollable_size(&self) -> LayerSize {
+ pub fn scrollable_size(&self) -> LayoutSize {
match self.node_type {
NodeType:: ScrollFrame(state) => state.scrollable_size,
- _ => LayerSize::zero(),
+ _ => LayoutSize::zero(),
}
}
pub fn scroll(&mut self, scroll_location: ScrollLocation) -> bool {
let scrolling = match self.node_type {
NodeType::ScrollFrame(ref mut scrolling) => scrolling,
_ => return false,
@@ -714,66 +714,66 @@ impl ClipScrollNode {
};
let z0 = -10000.0;
let z1 = 10000.0;
let p0 = inv.transform_point3d(&cursor.extend(z0));
let p1 = inv.transform_point3d(&cursor.extend(z1));
- if self.scrollable_size() == LayerSize::zero() {
+ if self.scrollable_size() == LayoutSize::zero() {
return false;
}
ray_intersects_rect(
p0.to_untyped(),
p1.to_untyped(),
self.local_viewport_rect.to_untyped(),
)
}
- pub fn scroll_offset(&self) -> LayerVector2D {
+ pub fn scroll_offset(&self) -> LayoutVector2D {
match self.node_type {
NodeType::ScrollFrame(ref scrolling) => scrolling.offset,
- _ => LayerVector2D::zero(),
+ _ => LayoutVector2D::zero(),
}
}
pub fn matches_external_id(&self, external_id: ExternalScrollId) -> bool {
match self.node_type {
NodeType::ScrollFrame(info) if info.external_id == Some(external_id) => true,
_ => false,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct ScrollFrameInfo {
- pub offset: LayerVector2D,
+ pub offset: LayoutVector2D,
pub scroll_sensitivity: ScrollSensitivity,
/// Amount that this ScrollFrame can scroll in both directions.
- pub scrollable_size: LayerSize,
+ pub scrollable_size: LayoutSize,
/// An external id to identify this scroll frame to API clients. This
/// allows setting scroll positions via the API without relying on ClipsIds
/// which may change between frames.
pub external_id: Option<ExternalScrollId>,
}
/// Manages scrolling offset.
impl ScrollFrameInfo {
pub fn new(
scroll_sensitivity: ScrollSensitivity,
- scrollable_size: LayerSize,
+ scrollable_size: LayoutSize,
external_id: Option<ExternalScrollId>,
) -> ScrollFrameInfo {
ScrollFrameInfo {
- offset: LayerVector2D::zero(),
+ offset: LayoutVector2D::zero(),
scroll_sensitivity,
scrollable_size,
external_id,
}
}
pub fn sensitive_to_input_events(&self) -> bool {
match self.scroll_sensitivity {
@@ -783,25 +783,25 @@ impl ScrollFrameInfo {
}
}
/// Contains information about reference frames.
#[derive(Copy, Clone, Debug)]
pub struct ReferenceFrameInfo {
/// The transformation that establishes this reference frame, relative to the parent
/// reference frame. The origin of the reference frame is included in the transformation.
- pub resolved_transform: LayerFastTransform,
+ pub resolved_transform: LayoutFastTransform,
/// The source transform and perspective matrices provided by the stacking context
/// that forms this reference frame. We maintain the property binding information
/// here so that we can resolve the animated transform and update the tree each
/// frame.
pub source_transform: PropertyBinding<LayoutTransform>,
pub source_perspective: LayoutFastTransform,
/// The original, not including the transform and relative to the parent reference frame,
/// origin of this reference frame. This is already rolled into the `transform' property, but
/// we also store it here to properly transform the viewport for sticky positioning.
- pub origin_in_parent_reference_frame: LayerVector2D,
+ pub origin_in_parent_reference_frame: LayoutVector2D,
/// True if the resolved transform is invertible.
pub invertible: bool,
}
--- a/gfx/webrender/src/clip_scroll_tree.rs
+++ b/gfx/webrender/src/clip_scroll_tree.rs
@@ -1,24 +1,24 @@
/* 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 api::{DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect, LayerVector2D};
+use api::{DeviceIntRect, DevicePixelScale, ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D};
use api::{PipelineId, ScrollClamping, ScrollLocation, ScrollNodeState};
use api::WorldPoint;
use clip::{ClipChain, ClipSourcesHandle, ClipStore};
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo};
use gpu_cache::GpuCache;
use gpu_types::{ClipScrollNodeIndex as GPUClipScrollNodeIndex, ClipScrollNodeData};
use internal_types::{FastHashMap, FastHashSet};
use print_tree::{PrintTree, PrintTreePrinter};
use resource_cache::ResourceCache;
use scene::SceneProperties;
-use util::{LayerFastTransform, LayerToWorldFastTransform};
+use util::{LayoutFastTransform, LayoutToWorldFastTransform};
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
/// An id that identifies coordinate systems in the ClipScrollTree. Each
/// coordinate system has an id and those ids will be shared when the coordinates
/// system are the same or are in the same axis-aligned space. This allows
/// for optimizing mask generation.
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -63,46 +63,46 @@ pub struct ClipScrollTree {
/// encountered during display list flattening. ClipChains are expected to never be
/// the children of ClipChains later in the list.
pub clip_chains_descriptors: Vec<ClipChainDescriptor>,
/// A vector of all ClipChains in this ClipScrollTree including those from
/// ClipChainDescriptors and also those defined by the clipping node hierarchy.
pub clip_chains: Vec<ClipChain>,
- pub pending_scroll_offsets: FastHashMap<ExternalScrollId, (LayerPoint, ScrollClamping)>,
+ pub pending_scroll_offsets: FastHashMap<ExternalScrollId, (LayoutPoint, ScrollClamping)>,
/// The current frame id, used for giving a unique id to all new dynamically
/// added frames and clips. The ClipScrollTree increments this by one every
/// time a new dynamic frame is created.
current_new_node_item: u64,
/// A set of pipelines which should be discarded the next time this
/// tree is drained.
pub pipelines_to_discard: FastHashSet<PipelineId>,
}
#[derive(Clone)]
pub struct TransformUpdateState {
- pub parent_reference_frame_transform: LayerToWorldFastTransform,
- pub parent_accumulated_scroll_offset: LayerVector2D,
- pub nearest_scrolling_ancestor_offset: LayerVector2D,
- pub nearest_scrolling_ancestor_viewport: LayerRect,
+ pub parent_reference_frame_transform: LayoutToWorldFastTransform,
+ pub parent_accumulated_scroll_offset: LayoutVector2D,
+ pub nearest_scrolling_ancestor_offset: LayoutVector2D,
+ pub nearest_scrolling_ancestor_viewport: LayoutRect,
/// The index of the current parent's clip chain.
pub parent_clip_chain_index: ClipChainIndex,
/// An id for keeping track of the axis-aligned space of this node. This is used in
/// order to to track what kinds of clip optimizations can be done for a particular
/// display list item, since optimizations can usually only be done among
/// 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: LayerFastTransform,
+ pub coordinate_system_relative_transform: LayoutFastTransform,
/// 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
/// node will not be clipped by clips that are transformed by this node.
pub invertible: bool,
}
impl ClipScrollTree {
@@ -195,17 +195,17 @@ impl ClipScrollTree {
self.pipelines_to_discard.clear();
self.clip_chains = vec![ClipChain::empty(&DeviceIntRect::zero())];
self.clip_chains_descriptors.clear();
scroll_states
}
pub fn scroll_node(
&mut self,
- origin: LayerPoint,
+ origin: LayoutPoint,
id: ExternalScrollId,
clamp: ScrollClamping
) -> bool {
for node in &mut self.nodes {
if node.matches_external_id(id) {
return node.set_scroll_origin(&origin, clamp);
}
}
@@ -241,23 +241,23 @@ impl ClipScrollTree {
if self.nodes.is_empty() {
return;
}
self.clip_chains[0] = ClipChain::empty(screen_rect);
let root_reference_frame_index = self.root_reference_frame_index();
let mut state = TransformUpdateState {
- parent_reference_frame_transform: LayerVector2D::new(pan.x, pan.y).into(),
- parent_accumulated_scroll_offset: LayerVector2D::zero(),
- nearest_scrolling_ancestor_offset: LayerVector2D::zero(),
- nearest_scrolling_ancestor_viewport: LayerRect::zero(),
+ parent_reference_frame_transform: LayoutVector2D::new(pan.x, pan.y).into(),
+ parent_accumulated_scroll_offset: LayoutVector2D::zero(),
+ nearest_scrolling_ancestor_offset: LayoutVector2D::zero(),
+ nearest_scrolling_ancestor_viewport: LayoutRect::zero(),
parent_clip_chain_index: ClipChainIndex(0),
current_coordinate_system_id: CoordinateSystemId::root(),
- coordinate_system_relative_transform: LayerFastTransform::identity(),
+ coordinate_system_relative_transform: LayoutFastTransform::identity(),
invertible: true,
};
let mut next_coordinate_system_id = state.current_coordinate_system_id.next();
self.update_node(
root_reference_frame_index,
&mut state,
&mut next_coordinate_system_id,
device_pixel_scale,
@@ -375,31 +375,31 @@ impl ClipScrollTree {
}
}
pub fn add_clip_node(
&mut self,
index: ClipScrollNodeIndex,
parent_index: ClipScrollNodeIndex,
handle: ClipSourcesHandle,
- clip_rect: LayerRect,
+ clip_rect: LayoutRect,
pipeline_id: PipelineId,
) -> ClipChainIndex {
let clip_chain_index = self.allocate_clip_chain();
let node_type = NodeType::Clip { handle, clip_chain_index, clip_chain_node: None };
let node = ClipScrollNode::new(pipeline_id, Some(parent_index), &clip_rect, node_type);
self.add_node(node, index);
clip_chain_index
}
pub fn add_sticky_frame(
&mut self,
index: ClipScrollNodeIndex,
parent_index: ClipScrollNodeIndex,
- frame_rect: LayerRect,
+ frame_rect: LayoutRect,
sticky_frame_info: StickyFrameInfo,
pipeline_id: PipelineId,
) {
let node = ClipScrollNode::new_sticky_frame(
parent_index,
frame_rect,
sticky_frame_info,
pipeline_id,
--- a/gfx/webrender/src/display_list_flattener.rs
+++ b/gfx/webrender/src/display_list_flattener.rs
@@ -1,20 +1,20 @@
/* 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 api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, ClipAndScrollInfo};
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{DevicePixelScale, DeviceUintRect, DisplayItemRef, Epoch, ExtendMode, ExternalScrollId};
-use api::{FilterOp, FontInstanceKey, FontRenderMode, GlyphInstance, GlyphOptions, GlyphRasterSpace, GradientStop};
-use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayerPoint, LayerPrimitiveInfo};
-use api::{LayerRect, LayerSize, LayerVector2D, LayoutRect, LayoutSize, LayoutTransform};
-use api::{LayoutVector2D, LineOrientation, LineStyle, LocalClip, PipelineId, PropertyBinding};
+use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, GradientStop};
+use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, LayoutPrimitiveInfo};
+use api::{LayoutRect, LayoutVector2D, LayoutSize, LayoutTransform};
+use api::{LineOrientation, LineStyle, LocalClip, PipelineId, PropertyBinding};
use api::{RepeatMode, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity, Shadow};
use api::{SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect, TileOffset};
use api::{TransformStyle, YuvColorSpace, YuvData};
use app_units::Au;
use border::ImageBorderSegment;
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore};
use clip_scroll_node::{ClipScrollNode, NodeType, StickyFrameInfo};
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, ClipScrollTree};
@@ -23,17 +23,17 @@ use frame_builder::{FrameBuilder, FrameB
use glyph_rasterizer::FontInstance;
use hit_test::{HitTestingItem, HitTestingRun};
use image::{decompose_image, TiledImageInfo};
use internal_types::{FastHashMap, FastHashSet};
use picture::PictureCompositeMode;
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, CachedGradient};
use prim_store::{CachedGradientIndex, ImageCacheKey, ImagePrimitiveCpu, ImageSource};
use prim_store::{PictureIndex, PrimitiveContainer, PrimitiveIndex, PrimitiveStore};
-use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
+use prim_store::{OpacityBinding, ScrollNodeAndClipChain, TextRunPrimitiveCpu};
use render_backend::{DocumentView};
use resource_cache::{FontInstanceMap, ImageRequest, TiledImageMap};
use scene::{Scene, ScenePipeline, StackingContextHelpers};
use scene_builder::{BuiltScene, SceneRequest};
use std::{f32, mem, usize};
use tiling::{CompositeOps, ScrollbarPrimitive};
use util::{MaxRect, RectHelpers, recycle_vec};
@@ -337,50 +337,50 @@ impl<'a> DisplayListFlattener<'a> {
GlyphRasterSpace::Screen,
);
// For the root pipeline, there's no need to add a full screen rectangle
// here, as it's handled by the framebuffer clear.
if self.scene.root_pipeline_id != Some(pipeline_id) {
if let Some(pipeline) = self.scene.pipelines.get(&pipeline_id) {
if let Some(bg_color) = pipeline.background_color {
- let root_bounds = LayerRect::new(LayerPoint::zero(), *frame_size);
- let info = LayerPrimitiveInfo::new(root_bounds);
+ let root_bounds = LayoutRect::new(LayoutPoint::zero(), *frame_size);
+ let info = LayoutPrimitiveInfo::new(root_bounds);
self.add_solid_rectangle(
reference_frame_info,
&info,
bg_color,
None,
Vec::new(),
);
}
}
}
- self.flatten_items(&mut pipeline.display_list.iter(), pipeline_id, LayerVector2D::zero());
+ self.flatten_items(&mut pipeline.display_list.iter(), pipeline_id, LayoutVector2D::zero());
if self.config.enable_scrollbars {
- let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0));
- let container_rect = LayerRect::new(LayerPoint::zero(), *frame_size);
+ let scrollbar_rect = LayoutRect::new(LayoutPoint::zero(), LayoutSize::new(10.0, 70.0));
+ let container_rect = LayoutRect::new(LayoutPoint::zero(), *frame_size);
self.add_scroll_bar(
reference_frame_info,
- &LayerPrimitiveInfo::new(scrollbar_rect),
+ &LayoutPrimitiveInfo::new(scrollbar_rect),
DEFAULT_SCROLLBAR_COLOR,
ScrollbarInfo(scroll_frame_info.scroll_node_id, container_rect),
);
}
self.pop_stacking_context();
}
fn flatten_items(
&mut self,
traversal: &mut BuiltDisplayListIter<'a>,
pipeline_id: PipelineId,
- reference_frame_relative_offset: LayerVector2D,
+ reference_frame_relative_offset: LayoutVector2D,
) {
loop {
let subtraversal = {
let item = match traversal.next() {
Some(item) => item,
None => break,
};
@@ -404,17 +404,17 @@ impl<'a> DisplayListFlattener<'a> {
}
fn flatten_sticky_frame(
&mut self,
item: &DisplayItemRef,
info: &StickyFrameDisplayItem,
clip_and_scroll: &ScrollNodeAndClipChain,
parent_id: &ClipId,
- reference_frame_relative_offset: &LayerVector2D,
+ reference_frame_relative_offset: &LayoutVector2D,
) {
let frame_rect = item.rect().translate(reference_frame_relative_offset);
let sticky_frame_info = StickyFrameInfo::new(
info.margins,
info.vertical_offset_bounds,
info.horizontal_offset_bounds,
info.previously_applied_offset,
);
@@ -431,17 +431,17 @@ impl<'a> DisplayListFlattener<'a> {
}
fn flatten_scroll_frame(
&mut self,
item: &DisplayItemRef,
info: &ScrollFrameDisplayItem,
pipeline_id: PipelineId,
clip_and_scroll_ids: &ClipAndScrollInfo,
- reference_frame_relative_offset: &LayerVector2D,
+ reference_frame_relative_offset: &LayoutVector2D,
) {
let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0);
let clip_region = ClipRegion::create_for_clip_node(
*item.clip_rect(),
complex_clips,
info.image_mask,
reference_frame_relative_offset,
);
@@ -470,17 +470,17 @@ impl<'a> DisplayListFlattener<'a> {
fn flatten_stacking_context(
&mut self,
traversal: &mut BuiltDisplayListIter<'a>,
pipeline_id: PipelineId,
item: &DisplayItemRef,
stacking_context: &StackingContext,
unreplaced_scroll_id: ClipId,
mut scroll_node_id: ClipId,
- mut reference_frame_relative_offset: LayerVector2D,
+ mut reference_frame_relative_offset: LayoutVector2D,
is_backface_visible: bool,
) {
// Avoid doing unnecessary work for empty stacking contexts.
if traversal.current_stacking_context_empty() {
traversal.skip_current_stacking_context();
return;
}
@@ -510,28 +510,28 @@ impl<'a> DisplayListFlattener<'a> {
// reference frame id. This means this stacking context establishes a new reference frame.
// Descendant fixed position content will be positioned relative to us.
if let Some(reference_frame_id) = stacking_context.reference_frame_id {
debug_assert!(
stacking_context.transform.is_some() ||
stacking_context.perspective.is_some()
);
- let reference_frame_bounds = LayerRect::new(LayerPoint::zero(), bounds.size);
+ let reference_frame_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
self.push_reference_frame(
reference_frame_id,
Some(scroll_node_id),
pipeline_id,
&reference_frame_bounds,
stacking_context.transform,
stacking_context.perspective,
reference_frame_relative_offset,
);
self.replacements.push((unreplaced_scroll_id, reference_frame_id));
- reference_frame_relative_offset = LayerVector2D::zero();
+ reference_frame_relative_offset = LayoutVector2D::zero();
}
// We apply the replacements one more time in case we need to set it to a replacement
// that we just pushed above.
let final_scroll_node = self.apply_scroll_frame_id_replacement(unreplaced_scroll_id);
self.push_stacking_context(
pipeline_id,
composition_operations,
@@ -561,17 +561,17 @@ impl<'a> DisplayListFlattener<'a> {
self.pop_stacking_context();
}
fn flatten_iframe(
&mut self,
item: &DisplayItemRef,
info: &IframeDisplayItem,
clip_and_scroll_ids: &ClipAndScrollInfo,
- reference_frame_relative_offset: &LayerVector2D,
+ reference_frame_relative_offset: &LayoutVector2D,
) {
let iframe_pipeline_id = info.pipeline_id;
let pipeline = match self.scene.pipelines.get(&iframe_pipeline_id) {
Some(pipeline) => pipeline,
None => {
//TODO: assert/debug_assert?
error!("Unknown pipeline used for iframe {:?}", info);
return
@@ -588,17 +588,17 @@ impl<'a> DisplayListFlattener<'a> {
reference_frame_relative_offset
),
);
let epoch = self.scene.pipeline_epochs[&iframe_pipeline_id];
self.pipeline_epochs.push((iframe_pipeline_id, epoch));
let bounds = item.rect();
- let iframe_rect = LayerRect::new(LayerPoint::zero(), bounds.size);
+ let iframe_rect = LayoutRect::new(LayoutPoint::zero(), bounds.size);
let origin = *reference_frame_relative_offset + bounds.origin.to_vector();
self.push_reference_frame(
ClipId::root_reference_frame(iframe_pipeline_id),
Some(info.clip_id),
iframe_pipeline_id,
&iframe_rect,
None,
None,
@@ -619,25 +619,25 @@ impl<'a> DisplayListFlattener<'a> {
self.pop_reference_frame();
}
fn flatten_item<'b>(
&'b mut self,
item: DisplayItemRef<'a, 'b>,
pipeline_id: PipelineId,
- reference_frame_relative_offset: LayerVector2D,
+ reference_frame_relative_offset: LayoutVector2D,
) -> Option<BuiltDisplayListIter<'a>> {
let mut clip_and_scroll_ids = item.clip_and_scroll();
let unreplaced_scroll_id = clip_and_scroll_ids.scroll_node_id;
clip_and_scroll_ids.scroll_node_id =
self.apply_scroll_frame_id_replacement(clip_and_scroll_ids.scroll_node_id);
let clip_and_scroll = self.id_to_index_mapper.map_clip_and_scroll(&clip_and_scroll_ids);
- let prim_info = item.get_layer_primitive_info(&reference_frame_relative_offset);
+ let prim_info = item.get_layout_primitive_info(&reference_frame_relative_offset);
match *item.item() {
SpecificDisplayItem::Image(ref info) => {
match self.tiled_image_map.get(&info.image_key).cloned() {
Some(tiling) => {
// The image resource is tiled. We have to generate an image primitive
// for each tile.
decompose_image(
&TiledImageInfo {
@@ -843,33 +843,33 @@ impl<'a> DisplayListFlattener<'a> {
// Do nothing; these are dummy items for the display list parser
SpecificDisplayItem::SetGradientStops => {}
SpecificDisplayItem::PopStackingContext => {
unreachable!("Should have returned in parent method.")
}
SpecificDisplayItem::PushShadow(shadow) => {
let mut prim_info = prim_info.clone();
- prim_info.rect = LayerRect::zero();
+ prim_info.rect = LayoutRect::zero();
self
.push_shadow(shadow, clip_and_scroll, &prim_info);
}
SpecificDisplayItem::PopAllShadows => {
self.pop_all_shadows();
}
}
None
}
/// Create a primitive and add it to the prim store. This method doesn't
/// add the primitive to the draw list, so can be used for creating
/// sub-primitives.
pub fn create_primitive(
&mut self,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
clip_sources: Vec<ClipSource>,
container: PrimitiveContainer,
) -> PrimitiveIndex {
let stacking_context = self.sc_stack.last().expect("bug: no stacking context!");
let clip_sources = if clip_sources.is_empty() {
None
} else {
@@ -883,17 +883,17 @@ impl<'a> DisplayListFlattener<'a> {
clip_sources,
info.tag,
container,
)
}
pub fn add_primitive_to_hit_testing_list(
&mut self,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
clip_and_scroll: ScrollNodeAndClipChain
) {
let tag = match info.tag {
Some(tag) => tag,
None => return,
};
let new_item = HitTestingItem::new(tag, info);
@@ -921,17 +921,17 @@ impl<'a> DisplayListFlattener<'a> {
pic.add_primitive(prim_index, clip_and_scroll);
}
/// Convenience interface that creates a primitive entry and adds it
/// to the draw list.
pub fn add_primitive(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
clip_sources: Vec<ClipSource>,
container: PrimitiveContainer,
) {
if !self.shadow_stack.is_empty() {
// TODO(gw): Restructure this so we don't need to move the shadow
// stack out (borrowck due to create_primitive below).
let shadow_stack = mem::replace(&mut self.shadow_stack, Vec::new());
for &(ref shadow, shadow_pic_index) in &shadow_stack {
@@ -992,17 +992,17 @@ impl<'a> DisplayListFlattener<'a> {
let current_reference_frame_index = self.current_reference_frame_index();
// An arbitrary large clip rect. For now, we don't
// specify a clip specific to the stacking context.
// However, now that they are represented as Picture
// primitives, we can apply any kind of clip mask
// to them, as for a normal primitive. This is needed
// to correctly handle some CSS cases (see #1957).
- let max_clip = LayerRect::max_rect();
+ let max_clip = LayoutRect::max_rect();
// If there is no root picture, create one for the main framebuffer.
if self.sc_stack.is_empty() {
// Should be no pictures at all if the stack is empty...
debug_assert!(self.prim_store.pictures.is_empty());
debug_assert_eq!(transform_style, TransformStyle::Flat);
// This picture stores primitive runs for items on the
@@ -1070,17 +1070,17 @@ impl<'a> DisplayListFlattener<'a> {
current_reference_frame_index,
None,
true,
);
let prim = BrushPrimitive::new_picture(container_index);
let prim_index = self.prim_store.add_primitive(
- &LayerRect::zero(),
+ &LayoutRect::zero(),
&max_clip,
is_backface_visible,
None,
None,
PrimitiveContainer::Brush(prim),
);
let parent_pic_index = *self.picture_stack.last().unwrap();
@@ -1119,17 +1119,17 @@ impl<'a> DisplayListFlattener<'a> {
pipeline_id,
current_reference_frame_index,
None,
true,
);
let src_prim = BrushPrimitive::new_picture(src_pic_index);
let src_prim_index = self.prim_store.add_primitive(
- &LayerRect::zero(),
+ &LayoutRect::zero(),
&max_clip,
is_backface_visible,
None,
None,
PrimitiveContainer::Brush(src_prim),
);
let parent_pic = &mut self.prim_store.pictures[parent_pic_index.0];
@@ -1149,17 +1149,17 @@ impl<'a> DisplayListFlattener<'a> {
current_reference_frame_index,
None,
true,
);
let src_prim = BrushPrimitive::new_picture(src_pic_index);
let src_prim_index = self.prim_store.add_primitive(
- &LayerRect::zero(),
+ &LayoutRect::zero(),
&max_clip,
is_backface_visible,
None,
None,
PrimitiveContainer::Brush(src_prim),
);
let parent_pic = &mut self.prim_store.pictures[parent_pic_index.0];
@@ -1206,43 +1206,36 @@ impl<'a> DisplayListFlattener<'a> {
true,
);
// Create a brush primitive that draws this picture.
let sc_prim = BrushPrimitive::new_picture(pic_index);
// Add the brush to the parent picture.
let sc_prim_index = self.prim_store.add_primitive(
- &LayerRect::zero(),
+ &LayoutRect::zero(),
&max_clip,
is_backface_visible,
None,
None,
PrimitiveContainer::Brush(sc_prim),
);
let parent_pic = &mut self.prim_store.pictures[parent_pic_index.0];
parent_pic.add_primitive(sc_prim_index, clip_and_scroll);
// Add this as the top-most picture for primitives to be added to.
self.picture_stack.push(pic_index);
- // TODO(gw): This is super conservative. We can expand on this a lot
- // once all the picture code is in place and landed.
- let allow_subpixel_aa = composite_ops.count() == 0 &&
- transform_style == TransformStyle::Flat &&
- composite_mode.is_none();
-
// Push the SC onto the stack, so we know how to handle things in
// pop_stacking_context.
let sc = FlattenedStackingContext {
composite_ops,
is_backface_visible,
pipeline_id,
- allow_subpixel_aa,
transform_style,
rendering_context_3d_pic_index,
glyph_raster_space,
};
self.sc_stack.push(sc);
}
@@ -1256,17 +1249,21 @@ impl<'a> DisplayListFlattener<'a> {
pop_count += sc.composite_ops.count();
// Remove the 3d context container if created
if sc.rendering_context_3d_pic_index.is_some() {
pop_count += 1;
}
for _ in 0 .. pop_count {
- self.picture_stack.pop().expect("bug: mismatched picture stack");
+ let pic_index = self
+ .picture_stack
+ .pop()
+ .expect("bug: mismatched picture stack");
+ self.prim_store.optimize_picture_if_possible(pic_index);
}
// By the time the stacking context stack is empty, we should
// also have cleared the picture stack.
if self.sc_stack.is_empty() {
self.picture_stack.pop().expect("bug: picture stack invalid");
debug_assert!(self.picture_stack.is_empty());
}
@@ -1277,20 +1274,20 @@ impl<'a> DisplayListFlattener<'a> {
);
}
pub fn push_reference_frame(
&mut self,
reference_frame_id: ClipId,
parent_id: Option<ClipId>,
pipeline_id: PipelineId,
- rect: &LayerRect,
+ rect: &LayoutRect,
source_transform: Option<PropertyBinding<LayoutTransform>>,
source_perspective: Option<LayoutTransform>,
- origin_in_parent_reference_frame: LayerVector2D,
+ origin_in_parent_reference_frame: LayoutVector2D,
) -> ClipScrollNodeIndex {
let index = self.id_to_index_mapper.get_node_index(reference_frame_id);
let node = ClipScrollNode::new_reference_frame(
parent_id.map(|id| self.id_to_index_mapper.get_node_index(id)),
rect,
source_transform,
source_perspective,
origin_in_parent_reference_frame,
@@ -1320,36 +1317,36 @@ impl<'a> DisplayListFlattener<'a> {
inner_rect: DeviceUintRect,
device_pixel_scale: DevicePixelScale,
) {
let viewport_offset = (inner_rect.origin.to_vector().to_f32() / device_pixel_scale).round();
let root_id = self.clip_scroll_tree.root_reference_frame_index();
let root_node = &mut self.clip_scroll_tree.nodes[root_id.0];
if let NodeType::ReferenceFrame(ref mut info) = root_node.node_type {
info.resolved_transform =
- LayerVector2D::new(viewport_offset.x, viewport_offset.y).into();
+ LayoutVector2D::new(viewport_offset.x, viewport_offset.y).into();
}
}
pub fn push_root(
&mut self,
pipeline_id: PipelineId,
- viewport_size: &LayerSize,
- content_size: &LayerSize,
+ viewport_size: &LayoutSize,
+ content_size: &LayoutSize,
) {
- let viewport_rect = LayerRect::new(LayerPoint::zero(), *viewport_size);
+ let viewport_rect = LayoutRect::new(LayoutPoint::zero(), *viewport_size);
self.push_reference_frame(
ClipId::root_reference_frame(pipeline_id),
None,
pipeline_id,
&viewport_rect,
None,
None,
- LayerVector2D::zero(),
+ LayoutVector2D::zero(),
);
self.add_scroll_frame(
ClipId::root_scroll_node(pipeline_id),
ClipId::root_reference_frame(pipeline_id),
Some(ExternalScrollId(0, pipeline_id)),
pipeline_id,
&viewport_rect,
@@ -1381,18 +1378,18 @@ impl<'a> DisplayListFlattener<'a> {
}
pub fn add_scroll_frame(
&mut self,
new_node_id: ClipId,
parent_id: ClipId,
external_id: Option<ExternalScrollId>,
pipeline_id: PipelineId,
- frame_rect: &LayerRect,
- content_size: &LayerSize,
+ frame_rect: &LayoutRect,
+ content_size: &LayoutSize,
scroll_sensitivity: ScrollSensitivity,
) -> ClipScrollNodeIndex {
let node_index = self.id_to_index_mapper.get_node_index(new_node_id);
let node = ClipScrollNode::new_scroll_frame(
pipeline_id,
self.id_to_index_mapper.get_node_index(parent_id),
external_id,
frame_rect,
@@ -1408,21 +1405,21 @@ impl<'a> DisplayListFlattener<'a> {
pub fn pop_reference_frame(&mut self) {
self.reference_frame_stack.pop();
}
pub fn push_shadow(
&mut self,
shadow: Shadow,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
) {
let pipeline_id = self.sc_stack.last().unwrap().pipeline_id;
let current_reference_frame_index = self.current_reference_frame_index();
- let max_clip = LayerRect::max_rect();
+ let max_clip = LayoutRect::max_rect();
// Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
// "the image that would be generated by applying to the shadow a
// Gaussian blur with a standard deviation equal to half the blur radius."
let std_deviation = shadow.blur_radius * 0.5;
// If the shadow has no blur, any elements will get directly rendered
// into the parent picture surface, instead of allocating and drawing
@@ -1441,17 +1438,17 @@ impl<'a> DisplayListFlattener<'a> {
current_reference_frame_index,
None,
apply_local_clip_rect,
);
// Create the primitive to draw the shadow picture into the scene.
let shadow_prim = BrushPrimitive::new_picture(shadow_pic_index);
let shadow_prim_index = self.prim_store.add_primitive(
- &LayerRect::zero(),
+ &LayoutRect::zero(),
&max_clip,
info.is_backface_visible,
None,
None,
PrimitiveContainer::Brush(shadow_prim),
);
// Add the shadow primitive. This must be done before pushing this
@@ -1463,47 +1460,45 @@ impl<'a> DisplayListFlattener<'a> {
pub fn pop_all_shadows(&mut self) {
assert!(self.shadow_stack.len() > 0, "popped shadows, but none were present");
self.shadow_stack.clear();
}
pub fn add_solid_rectangle(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
color: ColorF,
segments: Option<BrushSegmentDescriptor>,
extra_clips: Vec<ClipSource>,
) {
if color.a == 0.0 {
// Don't add transparent rectangles to the draw list, but do consider them for hit
// testing. This allows specifying invisible hit testing areas.
self.add_primitive_to_hit_testing_list(info, clip_and_scroll);
return;
}
let prim = BrushPrimitive::new(
- BrushKind::Solid {
- color,
- },
+ BrushKind::new_solid(color),
segments,
);
self.add_primitive(
clip_and_scroll,
info,
extra_clips,
PrimitiveContainer::Brush(prim),
);
}
pub fn add_clear_rectangle(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
) {
let prim = BrushPrimitive::new(
BrushKind::Clear,
None,
);
self.add_primitive(
clip_and_scroll,
@@ -1511,28 +1506,26 @@ impl<'a> DisplayListFlattener<'a> {
Vec::new(),
PrimitiveContainer::Brush(prim),
);
}
pub fn add_scroll_bar(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
color: ColorF,
scrollbar_info: ScrollbarInfo,
) {
if color.a == 0.0 {
return;
}
let prim = BrushPrimitive::new(
- BrushKind::Solid {
- color,
- },
+ BrushKind::new_solid(color),
None,
);
let prim_index = self.create_primitive(
info,
Vec::new(),
PrimitiveContainer::Brush(prim),
);
@@ -1547,26 +1540,24 @@ impl<'a> DisplayListFlattener<'a> {
scroll_frame_index: scrollbar_info.0,
frame_rect: scrollbar_info.1,
});
}
pub fn add_line(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
wavy_line_thickness: f32,
orientation: LineOrientation,
line_color: &ColorF,
style: LineStyle,
) {
let prim = BrushPrimitive::new(
- BrushKind::Solid {
- color: *line_color,
- },
+ BrushKind::new_solid(*line_color),
None,
);
let extra_clips = match style {
LineStyle::Solid => {
Vec::new()
}
LineStyle::Wavy |
@@ -1589,109 +1580,109 @@ impl<'a> DisplayListFlattener<'a> {
extra_clips,
PrimitiveContainer::Brush(prim),
);
}
pub fn add_border(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
border_item: &BorderDisplayItem,
gradient_stops: ItemRange<GradientStop>,
gradient_stops_count: usize,
) {
let rect = info.rect;
let create_segments = |outset: SideOffsets2D<f32>| {
// Calculate the modified rect as specific by border-image-outset
- let origin = LayerPoint::new(rect.origin.x - outset.left, rect.origin.y - outset.top);
- let size = LayerSize::new(
+ let origin = LayoutPoint::new(rect.origin.x - outset.left, rect.origin.y - outset.top);
+ let size = LayoutSize::new(
rect.size.width + outset.left + outset.right,
rect.size.height + outset.top + outset.bottom,
);
- let rect = LayerRect::new(origin, size);
+ let rect = LayoutRect::new(origin, size);
- let tl_outer = LayerPoint::new(rect.origin.x, rect.origin.y);
+ let tl_outer = LayoutPoint::new(rect.origin.x, rect.origin.y);
let tl_inner = tl_outer + vec2(border_item.widths.left, border_item.widths.top);
- let tr_outer = LayerPoint::new(rect.origin.x + rect.size.width, rect.origin.y);
+ let tr_outer = LayoutPoint::new(rect.origin.x + rect.size.width, rect.origin.y);
let tr_inner = tr_outer + vec2(-border_item.widths.right, border_item.widths.top);
- let bl_outer = LayerPoint::new(rect.origin.x, rect.origin.y + rect.size.height);
+ let bl_outer = LayoutPoint::new(rect.origin.x, rect.origin.y + rect.size.height);
let bl_inner = bl_outer + vec2(border_item.widths.left, -border_item.widths.bottom);
- let br_outer = LayerPoint::new(
+ let br_outer = LayoutPoint::new(
rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height,
);
let br_inner = br_outer - vec2(border_item.widths.right, border_item.widths.bottom);
// Build the list of gradient segments
vec![
// Top left
- LayerRect::from_floats(tl_outer.x, tl_outer.y, tl_inner.x, tl_inner.y),
+ LayoutRect::from_floats(tl_outer.x, tl_outer.y, tl_inner.x, tl_inner.y),
// Top right
- LayerRect::from_floats(tr_inner.x, tr_outer.y, tr_outer.x, tr_inner.y),
+ LayoutRect::from_floats(tr_inner.x, tr_outer.y, tr_outer.x, tr_inner.y),
// Bottom right
- LayerRect::from_floats(br_inner.x, br_inner.y, br_outer.x, br_outer.y),
+ LayoutRect::from_floats(br_inner.x, br_inner.y, br_outer.x, br_outer.y),
// Bottom left
- LayerRect::from_floats(bl_outer.x, bl_inner.y, bl_inner.x, bl_outer.y),
+ LayoutRect::from_floats(bl_outer.x, bl_inner.y, bl_inner.x, bl_outer.y),
// Top
- LayerRect::from_floats(tl_inner.x, tl_outer.y, tr_inner.x, tl_inner.y),
+ LayoutRect::from_floats(tl_inner.x, tl_outer.y, tr_inner.x, tl_inner.y),
// Bottom
- LayerRect::from_floats(bl_inner.x, bl_inner.y, br_inner.x, bl_outer.y),
+ LayoutRect::from_floats(bl_inner.x, bl_inner.y, br_inner.x, bl_outer.y),
// Left
- LayerRect::from_floats(tl_outer.x, tl_inner.y, tl_inner.x, bl_inner.y),
+ LayoutRect::from_floats(tl_outer.x, tl_inner.y, tl_inner.x, bl_inner.y),
// Right
- LayerRect::from_floats(tr_inner.x, tr_inner.y, br_outer.x, br_inner.y),
+ LayoutRect::from_floats(tr_inner.x, tr_inner.y, br_outer.x, br_inner.y),
]
};
match border_item.details {
BorderDetails::Image(ref border) => {
// Calculate the modified rect as specific by border-image-outset
- let origin = LayerPoint::new(
+ let origin = LayoutPoint::new(
rect.origin.x - border.outset.left,
rect.origin.y - border.outset.top,
);
- let size = LayerSize::new(
+ let size = LayoutSize::new(
rect.size.width + border.outset.left + border.outset.right,
rect.size.height + border.outset.top + border.outset.bottom,
);
- let rect = LayerRect::new(origin, size);
+ let rect = LayoutRect::new(origin, size);
// Calculate the local texel coords of the slices.
let px0 = 0.0;
let px1 = border.patch.slice.left as f32;
let px2 = border.patch.width as f32 - border.patch.slice.right as f32;
let px3 = border.patch.width as f32;
let py0 = 0.0;
let py1 = border.patch.slice.top as f32;
let py2 = border.patch.height as f32 - border.patch.slice.bottom as f32;
let py3 = border.patch.height as f32;
- let tl_outer = LayerPoint::new(rect.origin.x, rect.origin.y);
+ let tl_outer = LayoutPoint::new(rect.origin.x, rect.origin.y);
let tl_inner = tl_outer + vec2(border_item.widths.left, border_item.widths.top);
- let tr_outer = LayerPoint::new(rect.origin.x + rect.size.width, rect.origin.y);
+ let tr_outer = LayoutPoint::new(rect.origin.x + rect.size.width, rect.origin.y);
let tr_inner = tr_outer + vec2(-border_item.widths.right, border_item.widths.top);
- let bl_outer = LayerPoint::new(rect.origin.x, rect.origin.y + rect.size.height);
+ let bl_outer = LayoutPoint::new(rect.origin.x, rect.origin.y + rect.size.height);
let bl_inner = bl_outer + vec2(border_item.widths.left, -border_item.widths.bottom);
- let br_outer = LayerPoint::new(
+ let br_outer = LayoutPoint::new(
rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height,
);
let br_inner = br_outer - vec2(border_item.widths.right, border_item.widths.bottom);
fn add_segment(
segments: &mut Vec<ImageBorderSegment>,
- rect: LayerRect,
+ rect: LayoutRect,
uv_rect: TexelRect,
repeat_horizontal: RepeatMode,
repeat_vertical: RepeatMode) {
if uv_rect.uv1.x > uv_rect.uv0.x &&
uv_rect.uv1.y > uv_rect.uv0.y {
segments.push(ImageBorderSegment::new(
rect,
uv_rect,
@@ -1702,87 +1693,87 @@ impl<'a> DisplayListFlattener<'a> {
}
// Build the list of image segments
let mut segments = vec![];
// Top left
add_segment(
&mut segments,
- LayerRect::from_floats(tl_outer.x, tl_outer.y, tl_inner.x, tl_inner.y),
+ LayoutRect::from_floats(tl_outer.x, tl_outer.y, tl_inner.x, tl_inner.y),
TexelRect::new(px0, py0, px1, py1),
RepeatMode::Stretch,
RepeatMode::Stretch
);
// Top right
add_segment(
&mut segments,
- LayerRect::from_floats(tr_inner.x, tr_outer.y, tr_outer.x, tr_inner.y),
+ LayoutRect::from_floats(tr_inner.x, tr_outer.y, tr_outer.x, tr_inner.y),
TexelRect::new(px2, py0, px3, py1),
RepeatMode::Stretch,
RepeatMode::Stretch
);
// Bottom right
add_segment(
&mut segments,
- LayerRect::from_floats(br_inner.x, br_inner.y, br_outer.x, br_outer.y),
+ LayoutRect::from_floats(br_inner.x, br_inner.y, br_outer.x, br_outer.y),
TexelRect::new(px2, py2, px3, py3),
RepeatMode::Stretch,
RepeatMode::Stretch
);
// Bottom left
add_segment(
&mut segments,
- LayerRect::from_floats(bl_outer.x, bl_inner.y, bl_inner.x, bl_outer.y),
+ LayoutRect::from_floats(bl_outer.x, bl_inner.y, bl_inner.x, bl_outer.y),
TexelRect::new(px0, py2, px1, py3),
RepeatMode::Stretch,
RepeatMode::Stretch
);
// Center
if border.fill {
add_segment(
&mut segments,
- LayerRect::from_floats(tl_inner.x, tl_inner.y, tr_inner.x, bl_inner.y),
+ LayoutRect::from_floats(tl_inner.x, tl_inner.y, tr_inner.x, bl_inner.y),
TexelRect::new(px1, py1, px2, py2),
border.repeat_horizontal,
border.repeat_vertical
);
}
// Add edge segments.
// Top
add_segment(
&mut segments,
- LayerRect::from_floats(tl_inner.x, tl_outer.y, tr_inner.x, tl_inner.y),
+ LayoutRect::from_floats(tl_inner.x, tl_outer.y, tr_inner.x, tl_inner.y),
TexelRect::new(px1, py0, px2, py1),
border.repeat_horizontal,
RepeatMode::Stretch,
);
// Bottom
add_segment(
&mut segments,
- LayerRect::from_floats(bl_inner.x, bl_inner.y, br_inner.x, bl_outer.y),
+ LayoutRect::from_floats(bl_inner.x, bl_inner.y, br_inner.x, bl_outer.y),
TexelRect::new(px1, py2, px2, py3),
border.repeat_horizontal,
RepeatMode::Stretch,
);
// Left
add_segment(
&mut segments,
- LayerRect::from_floats(tl_outer.x, tl_inner.y, tl_inner.x, bl_inner.y),
+ LayoutRect::from_floats(tl_outer.x, tl_inner.y, tl_inner.x, bl_inner.y),
TexelRect::new(px0, py1, px1, py2),
RepeatMode::Stretch,
border.repeat_vertical,
);
// Right
add_segment(
&mut segments,
- LayerRect::from_floats(tr_inner.x, tr_inner.y, br_outer.x, br_inner.y),
+ LayoutRect::from_floats(tr_inner.x, tr_inner.y, br_outer.x, br_inner.y),
TexelRect::new(px2, py1, px3, py2),
RepeatMode::Stretch,
border.repeat_vertical,
);
for segment in segments {
let mut info = info.clone();
info.rect = segment.geom_rect;
@@ -1811,17 +1802,17 @@ impl<'a> DisplayListFlattener<'a> {
clip_and_scroll,
&info,
border.gradient.start_point - segment_rel,
border.gradient.end_point - segment_rel,
gradient_stops,
gradient_stops_count,
border.gradient.extend_mode,
segment.size,
- LayerSize::zero(),
+ LayoutSize::zero(),
);
},
BorderDetails::RadialGradient(ref border) => {
for segment in create_segments(border.outset) {
let segment_rel = segment.origin - rect.origin;
let mut info = info.clone();
info.rect = segment;
@@ -1830,29 +1821,29 @@ impl<'a> DisplayListFlattener<'a> {
&info,
border.gradient.center - segment_rel,
border.gradient.start_offset * border.gradient.radius.width,
border.gradient.end_offset * border.gradient.radius.width,
border.gradient.radius.width / border.gradient.radius.height,
gradient_stops,
border.gradient.extend_mode,
segment.size,
- LayerSize::zero(),
+ LayoutSize::zero(),
);
}
}
}
}
fn add_gradient_impl(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
- start_point: LayerPoint,
- end_point: LayerPoint,
+ info: &LayoutPrimitiveInfo,
+ start_point: LayoutPoint,
+ end_point: LayoutPoint,
stops: ItemRange<GradientStop>,
stops_count: usize,
extend_mode: ExtendMode,
gradient_index: CachedGradientIndex,
) {
// 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
@@ -1887,24 +1878,24 @@ impl<'a> DisplayListFlattener<'a> {
let prim = PrimitiveContainer::Brush(prim);
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
}
pub fn add_gradient(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
- start_point: LayerPoint,
- end_point: LayerPoint,
+ info: &LayoutPrimitiveInfo,
+ start_point: LayoutPoint,
+ end_point: LayoutPoint,
stops: ItemRange<GradientStop>,
stops_count: usize,
extend_mode: ExtendMode,
- tile_size: LayerSize,
- tile_spacing: LayerSize,
+ tile_size: LayoutSize,
+ tile_spacing: LayoutSize,
) {
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
self.cached_gradients.push(CachedGradient::new());
let prim_infos = info.decompose(
tile_size,
tile_spacing,
64 * 64,
@@ -1935,18 +1926,18 @@ impl<'a> DisplayListFlattener<'a> {
);
}
}
}
fn add_radial_gradient_impl(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
- center: LayerPoint,
+ info: &LayoutPrimitiveInfo,
+ center: LayoutPoint,
start_radius: f32,
end_radius: f32,
ratio_xy: f32,
stops: ItemRange<GradientStop>,
extend_mode: ExtendMode,
gradient_index: CachedGradientIndex,
) {
let prim = BrushPrimitive::new(
@@ -1968,25 +1959,25 @@ impl<'a> DisplayListFlattener<'a> {
Vec::new(),
PrimitiveContainer::Brush(prim),
);
}
pub fn add_radial_gradient(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
- center: LayerPoint,
+ info: &LayoutPrimitiveInfo,
+ center: LayoutPoint,
start_radius: f32,
end_radius: f32,
ratio_xy: f32,
stops: ItemRange<GradientStop>,
extend_mode: ExtendMode,
- tile_size: LayerSize,
- tile_spacing: LayerSize,
+ tile_size: LayoutSize,
+ tile_spacing: LayoutSize,
) {
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
self.cached_gradients.push(CachedGradient::new());
let prim_infos = info.decompose(
tile_size,
tile_spacing,
64 * 64,
@@ -2020,17 +2011,17 @@ impl<'a> DisplayListFlattener<'a> {
}
}
}
pub fn add_text(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
run_offset: LayoutVector2D,
- prim_info: &LayerPrimitiveInfo,
+ prim_info: &LayoutPrimitiveInfo,
font_instance_key: &FontInstanceKey,
text_color: &ColorF,
glyph_range: ItemRange<GlyphInstance>,
glyph_options: Option<GlyphOptions>,
) {
let prim = {
let instance_map = self.font_instances.read().unwrap();
let font_instance = match instance_map.get(font_instance_key) {
@@ -2064,36 +2055,21 @@ impl<'a> DisplayListFlattener<'a> {
.default_font_render_mode
.limit_by(font_instance.render_mode);
let mut flags = font_instance.flags;
if let Some(options) = glyph_options {
render_mode = render_mode.limit_by(options.render_mode);
flags |= options.flags;
}
- let (allow_subpixel_aa, glyph_raster_space) = match self.sc_stack.last() {
- Some(stacking_context) => {
- (stacking_context.allow_subpixel_aa, stacking_context.glyph_raster_space)
- }
- None => {
- (true, GlyphRasterSpace::Screen)
- }
+ let glyph_raster_space = match self.sc_stack.last() {
+ Some(stacking_context) => stacking_context.glyph_raster_space,
+ None => GlyphRasterSpace::Screen,
};
- // There are some conditions under which we can't use
- // subpixel text rendering, even if enabled.
- if !allow_subpixel_aa {
- // text on a picture that has filters
- // (e.g. opacity) can't use sub-pixel.
- // TODO(gw): It's possible we can relax this in
- // the future, if we modify the way
- // we handle subpixel blending.
- render_mode = render_mode.limit_by(FontRenderMode::Alpha);
- }
-
let prim_font = FontInstance::new(
font_instance.font_key,
font_instance.size,
*text_color,
font_instance.bg_color,
render_mode,
font_instance.subpx_dir,
flags,
@@ -2117,31 +2093,31 @@ impl<'a> DisplayListFlattener<'a> {
Vec::new(),
PrimitiveContainer::TextRun(prim),
);
}
pub fn add_image(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
- stretch_size: LayerSize,
- mut tile_spacing: LayerSize,
+ info: &LayoutPrimitiveInfo,
+ stretch_size: LayoutSize,
+ mut tile_spacing: LayoutSize,
sub_rect: Option<TexelRect>,
image_key: ImageKey,
image_rendering: ImageRendering,
alpha_type: AlphaType,
tile_offset: Option<TileOffset>,
) {
// If the tile spacing is the same as the rect size,
// then it is effectively zero. We use this later on
// in prim_store to detect if an image can be considered
// opaque.
if tile_spacing == info.rect.size {
- tile_spacing = LayerSize::zero();
+ tile_spacing = LayoutSize::zero();
}
let request = ImageRequest {
key: image_key,
rendering: image_rendering,
tile: tile_offset,
};
@@ -2155,28 +2131,29 @@ impl<'a> DisplayListFlattener<'a> {
(texel_rect.uv1.x - texel_rect.uv0.x) as i32,
(texel_rect.uv1.y - texel_rect.uv0.y) as i32,
),
)
});
// See if conditions are met to run through the new
// image brush shader, which supports segments.
- if tile_spacing == LayerSize::zero() &&
+ if tile_spacing == LayoutSize::zero() &&
stretch_size == info.rect.size &&
tile_offset.is_none() {
let prim = BrushPrimitive::new(
BrushKind::Image {
request,
current_epoch: Epoch::invalid(),
alpha_type,
stretch_size,
tile_spacing,
source: ImageSource::Default,
sub_rect,
+ opacity_binding: OpacityBinding::new(),
},
None,
);
self.add_primitive(
clip_and_scroll,
info,
Vec::new(),
@@ -2202,17 +2179,17 @@ impl<'a> DisplayListFlattener<'a> {
PrimitiveContainer::Image(prim_cpu),
);
}
}
pub fn add_yuv_image(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
- info: &LayerPrimitiveInfo,
+ info: &LayoutPrimitiveInfo,
yuv_data: YuvData,
color_space: YuvColorSpace,
image_rendering: ImageRendering,
) {
let format = yuv_data.get_format();
let yuv_key = match yuv_data {
YuvData::NV12(plane_0, plane_1) => [plane_0, plane_1, ImageKey::DUMMY],
YuvData::PlanarYCbCr(plane_0, plane_1, plane_2) => [plane_0, plane_1, plane_2],
@@ -2261,29 +2238,29 @@ pub fn build_scene(config: &FrameBuilder
clip_scroll_tree,
removed_pipelines: request.removed_pipelines,
}
}
trait PrimitiveInfoTiler {
fn decompose(
&self,
- tile_size: LayerSize,
- tile_spacing: LayerSize,
+ tile_size: LayoutSize,
+ tile_spacing: LayoutSize,
max_prims: usize,
- ) -> Vec<LayerPrimitiveInfo>;
+ ) -> Vec<LayoutPrimitiveInfo>;
}
-impl PrimitiveInfoTiler for LayerPrimitiveInfo {
+impl PrimitiveInfoTiler for LayoutPrimitiveInfo {
fn decompose(
&self,
- tile_size: LayerSize,
- tile_spacing: LayerSize,
+ tile_size: LayoutSize,
+ tile_spacing: LayoutSize,
max_prims: usize,
- ) -> Vec<LayerPrimitiveInfo> {
+ ) -> Vec<LayoutPrimitiveInfo> {
let mut prims = Vec::new();
let tile_repeat = tile_size + tile_spacing;
if tile_repeat.width <= 0.0 ||
tile_repeat.height <= 0.0 {
return prims;
}
@@ -2295,19 +2272,19 @@ impl PrimitiveInfoTiler for LayerPrimiti
let rect_p0 = self.rect.origin;
let rect_p1 = self.rect.bottom_right();
let mut y0 = rect_p0.y;
while y0 < rect_p1.y {
let mut x0 = rect_p0.x;
while x0 < rect_p1.x {
- prims.push(LayerPrimitiveInfo {
- rect: LayerRect::new(
- LayerPoint::new(x0, y0),
+ prims.push(LayoutPrimitiveInfo {
+ rect: LayoutRect::new(
+ LayoutPoint::new(x0, y0),
tile_size,
),
clip_rect,
is_backface_visible: self.is_backface_visible,
tag: self.tag,
});
// Mostly a safety against a crazy number of primitives
@@ -2337,28 +2314,23 @@ struct FlattenedStackingContext {
pipeline_id: PipelineId,
/// Filters / mix-blend-mode effects
composite_ops: CompositeOps,
/// If true, visible when backface is visible.
is_backface_visible: bool,
- /// Allow subpixel AA for text runs on this stacking context.
- /// This is a temporary hack while we don't support subpixel AA
- /// on transparent stacking contexts.
- allow_subpixel_aa: bool,
-
/// The rasterization mode for any text runs that are part
/// of this stacking context.
glyph_raster_space: GlyphRasterSpace,
/// CSS transform-style property.
transform_style: TransformStyle,
/// If Some(..), this stacking context establishes a new
/// 3d rendering context, and the value is the picture
// index of the 3d context container.
rendering_context_3d_pic_index: Option<PictureIndex>,
}
#[derive(Debug)]
-pub struct ScrollbarInfo(pub ClipScrollNodeIndex, pub LayerRect);
+pub struct ScrollbarInfo(pub ClipScrollNodeIndex, pub LayoutRect);
--- a/gfx/webrender/src/ellipse.rs
+++ b/gfx/webrender/src/ellipse.rs
@@ -1,27 +1,27 @@
/* 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 api::{LayerPoint, LayerSize, LayerVector2D};
+use api::{LayoutPoint, LayoutSize, LayoutVector2D};
use std::f32::consts::FRAC_PI_2;
/// Number of steps to integrate arc length over.
const STEP_COUNT: usize = 20;
/// Represents an ellipse centred at a local space origin.
#[derive(Debug, Clone)]
pub struct Ellipse {
- pub radius: LayerSize,
+ pub radius: LayoutSize,
pub total_arc_length: f32,
}
impl Ellipse {
- pub fn new(radius: LayerSize) -> Ellipse {
+ pub fn new(radius: LayoutSize) -> Ellipse {
// Approximate the total length of the first quadrant of this ellipse.
let total_arc_length = get_simpson_length(FRAC_PI_2, radius.width, radius.height);
Ellipse {
radius,
total_arc_length,
}
}
@@ -51,42 +51,42 @@ impl Ellipse {
}
}
theta
}
/// Get a point and tangent on this ellipse from a given angle.
/// This only works for the first quadrant of the ellipse.
- pub fn get_point_and_tangent(&self, theta: f32) -> (LayerPoint, LayerPoint) {
+ pub fn get_point_and_tangent(&self, theta: f32) -> (LayoutPoint, LayoutPoint) {
let (sin_theta, cos_theta) = theta.sin_cos();
- let point = LayerPoint::new(
+ let point = LayoutPoint::new(
self.radius.width * cos_theta,
self.radius.height * sin_theta,
);
- let tangent = LayerPoint::new(
+ let tangent = LayoutPoint::new(
-self.radius.width * sin_theta,
self.radius.height * cos_theta,
);
(point, tangent)
}
- pub fn contains(&self, point: LayerPoint) -> bool {
+ pub fn contains(&self, point: LayoutPoint) -> bool {
self.signed_distance(point.to_vector()) <= 0.0
}
/// Find the signed distance from this ellipse given a point.
/// Taken from http://www.iquilezles.org/www/articles/ellipsedist/ellipsedist.htm
- fn signed_distance(&self, point: LayerVector2D) -> f32 {
+ fn signed_distance(&self, point: LayoutVector2D) -> f32 {
// This algorithm fails for circles, so we handle them here.
if self.radius.width == self.radius.height {
return point.length() - self.radius.width;
}
- let mut p = LayerVector2D::new(point.x.abs(), point.y.abs());
+ let mut p = LayoutVector2D::new(point.x.abs(), point.y.abs());
let mut ab = self.radius.to_vector();
if p.x > p.y {
p = p.yx();
ab = ab.yx();
}
let l = ab.y * ab.y - ab.x * ab.x;
@@ -116,17 +116,17 @@ impl Ellipse {
let rx = -s - u - c * 4.0 + 2.0 * m2;
let ry = (s - u) * (3.0_f32).sqrt();
let rm = (rx * rx + ry * ry).sqrt();
let p = ry / (rm - rx).sqrt();
(p + 2.0 * g / rm - m) / 2.0
};
let si = (1.0 - co * co).sqrt();
- let r = LayerVector2D::new(ab.x * co, ab.y * si);
+ let r = LayoutVector2D::new(ab.x * co, ab.y * si);
(r - p).length() * (p.y - r.y).signum()
}
}
/// Use Simpsons rule to approximate the arc length of
/// part of an ellipse. Note that this only works over
/// the range of [0, pi/2].
// TODO(gw): This is a simplistic way to estimate the
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -1,15 +1,15 @@
/* 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 api::{BuiltDisplayList, ColorF, DeviceIntPoint, DeviceIntRect, DevicePixelScale};
use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentLayer, FontRenderMode};
-use api::{LayerRect, LayerSize, PipelineId, WorldPoint};
+use api::{LayoutRect, LayoutSize, PipelineId, WorldPoint};
use clip::{ClipChain, ClipStore};
use clip_scroll_node::{ClipScrollNode};
use clip_scroll_tree::{ClipScrollNodeIndex, ClipScrollTree};
use display_list_flattener::{DisplayListFlattener};
use gpu_cache::GpuCache;
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData};
use hit_test::{HitTester, HitTestingRun};
use internal_types::{FastHashMap};
@@ -19,17 +19,17 @@ use profiler::{FrameProfileCounters, Gpu
use render_backend::FrameId;
use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
use resource_cache::{ResourceCache};
use scene::{ScenePipeline, SceneProperties};
use std::{mem, f32};
use std::sync::Arc;
use tiling::{Frame, RenderPass, RenderPassKind, RenderTargetContext};
use tiling::{ScrollbarPrimitive, SpecialRenderPasses};
-use util::{self, MaxRect, WorldToLayerFastTransform};
+use util::{self, MaxRect, WorldToLayoutFastTransform};
#[derive(Clone, Copy)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FrameBuilderConfig {
pub enable_scrollbars: bool,
pub default_font_render_mode: FontRenderMode,
pub dual_source_blending_is_supported: bool,
@@ -57,31 +57,32 @@ pub struct FrameBuildingContext<'a> {
pub clip_scroll_tree: &'a ClipScrollTree,
pub node_data: &'a [ClipScrollNodeData],
}
pub struct FrameBuildingState<'a> {
pub render_tasks: &'a mut RenderTaskTree,
pub profile_counters: &'a mut FrameProfileCounters,
pub clip_store: &'a mut ClipStore,
- pub local_clip_rects: &'a mut Vec<LayerRect>,
+ pub local_clip_rects: &'a mut Vec<LayoutRect>,
pub resource_cache: &'a mut ResourceCache,
pub gpu_cache: &'a mut GpuCache,
pub cached_gradients: &'a mut [CachedGradient],
pub special_render_passes: &'a mut SpecialRenderPasses,
}
pub struct PictureContext<'a> {
pub pipeline_id: PipelineId,
pub prim_runs: Vec<PrimitiveRun>,
pub original_reference_frame_index: Option<ClipScrollNodeIndex>,
pub display_list: &'a BuiltDisplayList,
- pub inv_world_transform: Option<WorldToLayerFastTransform>,
+ pub inv_world_transform: Option<WorldToLayoutFastTransform>,
pub apply_local_clip_rect: bool,
pub inflation_factor: f32,
+ pub allow_subpixel_aa: bool,
}
pub struct PictureState {
pub tasks: Vec<RenderTaskId>,
pub has_non_root_coord_system: bool,
}
impl PictureState {
@@ -160,17 +161,17 @@ impl FrameBuilder {
pipelines: &FastHashMap<PipelineId, Arc<ScenePipeline>>,
resource_cache: &mut ResourceCache,
gpu_cache: &mut GpuCache,
render_tasks: &mut RenderTaskTree,
special_render_passes: &mut SpecialRenderPasses,
profile_counters: &mut FrameProfileCounters,
device_pixel_scale: DevicePixelScale,
scene_properties: &SceneProperties,
- local_clip_rects: &mut Vec<LayerRect>,
+ local_clip_rects: &mut Vec<LayoutRect>,
node_data: &[ClipScrollNodeData],
) -> Option<RenderTaskId> {
profile_scope!("cull");
if self.prim_store.pictures.is_empty() {
return None
}
@@ -206,16 +207,17 @@ impl FrameBuilder {
let pic_context = PictureContext {
pipeline_id: root_clip_scroll_node.pipeline_id,
prim_runs: mem::replace(&mut self.prim_store.pictures[0].runs, Vec::new()),
original_reference_frame_index: None,
display_list,
inv_world_transform: None,
apply_local_clip_rect: true,
inflation_factor: 0.0,
+ allow_subpixel_aa: true,
};
let mut pic_state = PictureState::new();
self.prim_store.reset_prim_visibility();
self.prim_store.prepare_prim_runs(
&pic_context,
&mut pic_state,
@@ -245,17 +247,17 @@ impl FrameBuilder {
let metadata = &mut self.prim_store.cpu_metadata[scrollbar_prim.prim_index.0];
let scroll_frame = &clip_scroll_tree.nodes[scrollbar_prim.scroll_frame_index.0];
// Invalidate what's in the cache so it will get rebuilt.
gpu_cache.invalidate(&metadata.gpu_location);
let scrollable_distance = scroll_frame.scrollable_size().height;
if scrollable_distance <= 0.0 {
- metadata.local_clip_rect.size = LayerSize::zero();
+ metadata.local_clip_rect.size = LayoutSize::zero();
continue;
}
let amount_scrolled = -scroll_frame.scroll_offset().y / scrollable_distance;
let frame_rect = scrollbar_prim.frame_rect;
let min_y = frame_rect.origin.y + SCROLLBAR_PADDING;
let max_y = frame_rect.origin.y + frame_rect.size.height -
(SCROLLBAR_PADDING + metadata.local_rect.size.height);
@@ -294,17 +296,17 @@ impl FrameBuilder {
resource_cache.begin_frame(frame_id);
gpu_cache.begin_frame();
let mut node_data = Vec::with_capacity(clip_scroll_tree.nodes.len());
let total_prim_runs =
self.prim_store.pictures.iter().fold(1, |count, pic| count + pic.runs.len());
let mut clip_chain_local_clip_rects = Vec::with_capacity(total_prim_runs);
- clip_chain_local_clip_rects.push(LayerRect::max_rect());
+ clip_chain_local_clip_rects.push(LayoutRect::max_rect());
clip_scroll_tree.update_tree(
&self.screen_rect.to_i32(),
device_pixel_scale,
&mut self.clip_store,
resource_cache,
gpu_cache,
pan,
--- a/gfx/webrender/src/glyph_rasterizer.rs
+++ b/gfx/webrender/src/glyph_rasterizer.rs
@@ -2,17 +2,17 @@
* 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/. */
#[cfg(test)]
use api::{IdNamespace, LayoutPoint};
use api::{ColorF, ColorU};
use api::{FontInstanceFlags, FontInstancePlatformOptions};
use api::{FontKey, FontRenderMode, FontTemplate, FontVariation};
-use api::{GlyphDimensions, GlyphKey, LayerToWorldTransform, SubpixelDirection};
+use api::{GlyphDimensions, GlyphKey, LayoutToWorldTransform, SubpixelDirection};
#[cfg(feature = "pathfinder")]
use api::NativeFontHandle;
#[cfg(any(test, feature = "pathfinder"))]
use api::DeviceIntSize;
#[cfg(not(feature = "pathfinder"))]
use api::{ImageData, ImageDescriptor, ImageFormat};
use app_units::Au;
#[cfg(not(feature = "pathfinder"))]
@@ -32,19 +32,19 @@ use platform::font::FontContext;
use profiler::TextureCacheProfileCounters;
use rayon::ThreadPool;
#[cfg(not(feature = "pathfinder"))]
use rayon::prelude::*;
#[cfg(test)]
use render_backend::FrameId;
use render_task::{RenderTaskCache, RenderTaskTree};
#[cfg(feature = "pathfinder")]
-use render_task::{RenderTask, RenderTaskCacheKey, RenderTaskCacheKeyKind};
+use render_task::{RenderTask, RenderTaskCacheKey, RenderTaskCacheEntryHandle};
#[cfg(feature = "pathfinder")]
-use render_task::{RenderTaskId, RenderTaskLocation};
+use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
#[cfg(feature = "pathfinder")]
use resource_cache::CacheItem;
use std::cmp;
use std::collections::hash_map::Entry;
use std::f32;
use std::hash::{Hash, Hasher};
use std::mem;
use std::sync::{Arc, Mutex, MutexGuard};
@@ -179,18 +179,18 @@ impl FontTransform {
FontTransform::new(-self.scale_x, self.skew_x, -self.skew_y, self.scale_y)
}
pub fn flip_y(&self) -> Self {
FontTransform::new(self.scale_x, -self.skew_y, self.skew_y, -self.scale_y)
}
}
-impl<'a> From<&'a LayerToWorldTransform> for FontTransform {
- fn from(xform: &'a LayerToWorldTransform) -> Self {
+impl<'a> From<&'a LayoutToWorldTransform> for FontTransform {
+ fn from(xform: &'a LayoutToWorldTransform) -> Self {
FontTransform::new(xform.m11, xform.m21, xform.m12, xform.m22)
}
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FontInstance {
@@ -412,17 +412,17 @@ impl GlyphRasterizer {
}
let pathfinder_context = create_pathfinder_font_context()?;
Ok(GlyphRasterizer {
font_contexts: Arc::new(FontContexts {
worker_contexts: contexts,
shared_context: Mutex::new(shared_context),
- pathfinder_context: pathfinder_context,
+ pathfinder_context,
workers: Arc::clone(&workers),
}),
pending_glyphs: 0,
glyph_rx,
glyph_tx,
workers,
fonts_to_remove: Vec::new(),
next_gpu_glyph_cache_key: GpuGlyphCacheKey(0),
@@ -499,38 +499,40 @@ impl GlyphRasterizer {
glyph_key: &GlyphKey,
font: &FontInstance,
cached_glyph_info: CachedGlyphInfo,
texture_cache: &mut TextureCache,
gpu_cache: &mut GpuCache,
render_task_cache: &mut RenderTaskCache,
render_task_tree: &mut RenderTaskTree,
render_passes: &mut SpecialRenderPasses)
- -> Result<(CacheItem, GlyphFormat), ()> {
+ -> Result<(RenderTaskCacheEntryHandle,
+ GlyphFormat), ()> {
let mut pathfinder_font_context = self.font_contexts.lock_pathfinder_context();
let render_task_cache_key = cached_glyph_info.render_task_cache_key;
let (glyph_origin, glyph_size) = (cached_glyph_info.origin, render_task_cache_key.size);
let user_data = [glyph_origin.x as f32, (glyph_origin.y - glyph_size.height) as f32, 1.0];
- let cache_item = try!(render_task_cache.request_render_task(render_task_cache_key,
- texture_cache,
- gpu_cache,
- render_task_tree,
- Some(user_data),
- |render_tasks| {
+ let handle = try!(render_task_cache.request_render_task(render_task_cache_key,
+ texture_cache,
+ gpu_cache,
+ render_task_tree,
+ Some(user_data),
+ false,
+ |render_tasks| {
// TODO(pcwalton): Non-subpixel font render mode.
request_render_task_from_pathfinder(glyph_key,
font,
&glyph_origin,
&glyph_size,
&mut *pathfinder_font_context,
font.render_mode,
render_tasks,
render_passes)
}));
- Ok((cache_item, font.get_glyph_format()))
+ Ok((handle, font.get_glyph_format()))
}
#[cfg(feature = "pathfinder")]
pub fn request_glyphs(
&mut self,
glyph_cache: &mut GlyphCache,
font: FontInstance,
glyph_keys: &[GlyphKey],
@@ -592,30 +594,30 @@ impl GlyphRasterizer {
origin: DeviceIntPoint::new(glyph_dimensions.origin.x as i32,
-glyph_dimensions.origin.y as i32),
};
self.next_gpu_glyph_cache_key.0 += 1;
cached_glyph_info
}
};
- let cache_entry =
+ let handle =
match self.request_glyph_from_pathfinder_if_necessary(glyph_key,
&font,
cached_glyph_info.clone(),
texture_cache,
gpu_cache,
render_task_cache,
render_task_tree,
render_passes) {
Ok(_) => GlyphCacheEntry::Cached(cached_glyph_info),
Err(_) => GlyphCacheEntry::Blank,
};
- glyph_key_cache.insert(glyph_key.clone(), cache_entry);
+ glyph_key_cache.insert(glyph_key.clone(), handle);
}
}
#[cfg(not(feature = "pathfinder"))]
pub fn request_glyphs(
&mut self,
glyph_cache: &mut GlyphCache,
font: FontInstance,
@@ -1021,17 +1023,17 @@ fn compute_embolden_amount(ppem: f32) ->
fn request_render_task_from_pathfinder(glyph_key: &GlyphKey,
font: &FontInstance,
glyph_origin: &DeviceIntPoint,
glyph_size: &DeviceIntSize,
font_context: &mut PathfinderFontContext,
render_mode: FontRenderMode,
render_tasks: &mut RenderTaskTree,
render_passes: &mut SpecialRenderPasses)
- -> Result<(RenderTaskId, bool), ()> {
+ -> Result<RenderTaskId, ()> {
let pathfinder_font_instance = pathfinder_font_renderer::FontInstance {
font_key: font.font_key.clone(),
size: font.size,
};
let pathfinder_subpixel_offset =
pathfinder_font_renderer::SubpixelOffset(glyph_key.subpixel_offset as u8);
let glyph_subpixel_offset: f64 = glyph_key.subpixel_offset.into();
@@ -1048,28 +1050,28 @@ fn request_render_task_from_pathfinder(g
// FIXME(pcwalton): Support vertical subpixel offsets.
// FIXME(pcwalton): Embolden amount should be 0 on macOS if "Use LCD font
// smoothing" is unchecked in System Preferences.
let subpixel_offset = TypedPoint2D::new(glyph_subpixel_offset as f32, 0.0);
let embolden_amount = compute_embolden_amount(font.size.to_f32_px());
- let location = RenderTaskLocation::Dynamic(None, *glyph_size);
+ let location = RenderTaskLocation::Dynamic(None, Some(*glyph_size));
let glyph_render_task = RenderTask::new_glyph(location,
mesh,
&glyph_origin,
&subpixel_offset,
font.render_mode,
&embolden_amount);
let root_task_id = render_tasks.add(glyph_render_task);
let render_pass = match render_mode {
FontRenderMode::Mono | FontRenderMode::Alpha => &mut render_passes.alpha_glyph_pass,
FontRenderMode::Subpixel => &mut render_passes.color_glyph_pass,
};
render_pass.add_render_task(root_task_id, *glyph_size, RenderTargetKind::Color);
- Ok((root_task_id, false))
+ Ok(root_task_id)
}
#[cfg(feature = "pathfinder")]
pub struct NativeFontHandleWrapper<'a>(pub &'a NativeFontHandle);
--- a/gfx/webrender/src/gpu_types.rs
+++ b/gfx/webrender/src/gpu_types.rs
@@ -1,13 +1,13 @@
/* 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 api::{DevicePoint, LayerToWorldTransform, WorldToLayerTransform};
+use api::{DevicePoint, LayoutToWorldTransform, WorldToLayoutTransform};
use gpu_cache::{GpuCacheAddress, GpuDataRequest};
use prim_store::EdgeAaSegmentMask;
use render_task::RenderTaskAddress;
// Contains type that must exactly match the same structures declared in GLSL.
#[derive(Copy, Clone, Debug)]
#[repr(C)]
@@ -78,16 +78,26 @@ pub struct BlurInstance {
pub struct ClipMaskInstance {
pub render_task_address: RenderTaskAddress,
pub scroll_node_data_index: ClipScrollNodeIndex,
pub segment: i32,
pub clip_data_address: GpuCacheAddress,
pub resource_address: GpuCacheAddress,
}
+/// A border corner dot or dash drawn into the clipping mask.
+#[derive(Debug, Copy, Clone)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[repr(C)]
+pub struct ClipMaskBorderCornerDotDash {
+ pub clip_mask_instance: ClipMaskInstance,
+ pub dot_dash_data: [f32; 8],
+}
+
// 32 bytes per instance should be enough for anyone!
#[derive(Debug, Clone)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PrimitiveInstance {
data: [i32; 8],
}
@@ -241,27 +251,27 @@ impl From<BrushInstance> for PrimitiveIn
#[repr(C)]
pub struct ClipScrollNodeIndex(pub u32);
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[repr(C)]
pub struct ClipScrollNodeData {
- pub transform: LayerToWorldTransform,
- pub inv_transform: WorldToLayerTransform,
+ pub transform: LayoutToWorldTransform,
+ pub inv_transform: WorldToLayoutTransform,
pub transform_kind: f32,
pub padding: [f32; 3],
}
impl ClipScrollNodeData {
pub fn invalid() -> Self {
ClipScrollNodeData {
- transform: LayerToWorldTransform::identity(),
- inv_transform: WorldToLayerTransform::identity(),
+ transform: LayoutToWorldTransform::identity(),
+ inv_transform: WorldToLayoutTransform::identity(),
transform_kind: 0.0,
padding: [0.0; 3],
}
}
}
#[derive(Copy, Debug, Clone, PartialEq)]
#[repr(C)]
--- a/gfx/webrender/src/hit_test.rs
+++ b/gfx/webrender/src/hit_test.rs
@@ -1,40 +1,40 @@
/* 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 api::{BorderRadius, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag, LayerPoint};
-use api::{LayerPrimitiveInfo, LayerRect, PipelineId, WorldPoint};
+use api::{BorderRadius, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag, LayoutPoint};
+use api::{LayoutPrimitiveInfo, LayoutRect, PipelineId, WorldPoint};
use clip::{ClipSource, ClipStore, rounded_rectangle_contains_point};
use clip_scroll_node::{ClipScrollNode, NodeType};
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, ClipScrollTree};
use internal_types::FastHashMap;
use prim_store::ScrollNodeAndClipChain;
-use util::LayerToWorldFastTransform;
+use util::LayoutToWorldFastTransform;
/// A copy of important clip scroll node data to use during hit testing. This a copy of
/// data from the ClipScrollTree that will persist as a new frame is under construction,
/// allowing hit tests consistent with the currently rendered frame.
pub struct HitTestClipScrollNode {
/// The pipeline id of this node.
pipeline_id: PipelineId,
/// A particular point must be inside all of these regions to be considered clipped in
/// for the purposes of a hit test.
regions: Vec<HitTestRegion>,
/// World transform for content transformed by this node.
- world_content_transform: LayerToWorldFastTransform,
+ world_content_transform: LayoutToWorldFastTransform,
/// World viewport transform for content transformed by this node.
- world_viewport_transform: LayerToWorldFastTransform,
+ world_viewport_transform: LayoutToWorldFastTransform,
/// Origin of the viewport of the node, used to calculate node-relative positions.
- node_origin: LayerPoint,
+ node_origin: LayoutPoint,
}
/// A description of a clip chain in the HitTester. This is used to describe
/// hierarchical clip scroll nodes as well as ClipChains, so that they can be
/// handled the same way during hit testing. Once we represent all ClipChains
/// using ClipChainDescriptors, we can get rid of this and just use the
/// ClipChainDescriptor here.
#[derive(Clone)]
@@ -49,43 +49,43 @@ impl HitTestClipChainDescriptor {
parent: None,
clips: Vec::new(),
}
}
}
#[derive(Clone)]
pub struct HitTestingItem {
- rect: LayerRect,
- clip_rect: LayerRect,
+ rect: LayoutRect,
+ clip_rect: LayoutRect,
tag: ItemTag,
is_backface_visible: bool,
}
impl HitTestingItem {
- pub fn new(tag: ItemTag, info: &LayerPrimitiveInfo) -> HitTestingItem {
+ pub fn new(tag: ItemTag, info: &LayoutPrimitiveInfo) -> HitTestingItem {
HitTestingItem {
rect: info.rect,
clip_rect: info.clip_rect,
- tag: tag,
+ tag,
is_backface_visible: info.is_backface_visible,
}
}
}
#[derive(Clone)]
pub struct HitTestingRun(pub Vec<HitTestingItem>, pub ScrollNodeAndClipChain);
enum HitTestRegion {
- Rectangle(LayerRect, ClipMode),
- RoundedRectangle(LayerRect, BorderRadius, ClipMode),
+ Rectangle(LayoutRect, ClipMode),
+ RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
}
impl HitTestRegion {
- pub fn contains(&self, point: &LayerPoint) -> bool {
+ pub fn contains(&self, point: &LayoutPoint) -> bool {
match *self {
HitTestRegion::Rectangle(ref rectangle, ClipMode::Clip) =>
rectangle.contains(point),
HitTestRegion::Rectangle(ref rectangle, ClipMode::ClipOut) =>
!rectangle.contains(point),
HitTestRegion::RoundedRectangle(rect, radii, ClipMode::Clip) =>
rounded_rectangle_contains_point(point, &rect, &radii),
HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
@@ -322,17 +322,17 @@ fn get_regions_for_clip_scroll_node(
}
}).collect()
}
pub struct HitTest {
pipeline_id: Option<PipelineId>,
point: WorldPoint,
flags: HitTestFlags,
- node_cache: FastHashMap<ClipScrollNodeIndex, Option<LayerPoint>>,
+ node_cache: FastHashMap<ClipScrollNodeIndex, Option<LayoutPoint>>,
clip_chain_cache: Vec<Option<bool>>,
}
impl HitTest {
pub fn new(
pipeline_id: Option<PipelineId>,
point: WorldPoint,
flags: HitTestFlags,
@@ -361,14 +361,14 @@ impl HitTest {
self.clip_chain_cache[index.0] = Some(value);
}
pub fn get_absolute_point(&self, hit_tester: &HitTester) -> WorldPoint {
if !self.flags.contains(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT) {
return self.point;
}
- let point = &LayerPoint::new(self.point.x, self.point.y);
+ let point = &LayoutPoint::new(self.point.x, self.point.y);
self.pipeline_id.map(|id|
hit_tester.get_pipeline_root(id).world_viewport_transform.transform_point2d(point)
).unwrap_or_else(|| WorldPoint::new(self.point.x, self.point.y))
}
}
--- a/gfx/webrender/src/image.rs
+++ b/gfx/webrender/src/image.rs
@@ -1,28 +1,28 @@
/* 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 api::{TileOffset, LayerRect, LayerSize, LayerVector2D, DeviceUintSize};
+use api::{TileOffset, LayoutRect, LayoutSize, LayoutVector2D, DeviceUintSize};
use euclid::rect;
pub struct DecomposedTile {
- pub rect: LayerRect,
- pub stretch_size: LayerSize,
+ pub rect: LayoutRect,
+ pub stretch_size: LayoutSize,
pub tile_offset: TileOffset,
}
pub struct TiledImageInfo {
/// The bounds of the item in layout space.
- pub rect: LayerRect,
+ pub rect: LayoutRect,
/// The space between each repeated pattern in layout space.
- pub tile_spacing: LayerSize,
+ pub tile_spacing: LayoutSize,
/// The size in layout space of each repetition of the image.
- pub stretch_size: LayerSize,
+ pub stretch_size: LayoutSize,
/// The size the image occupies in the cache in device space.
pub device_image_size: DeviceUintSize,
/// The size of the tiles in the cache in device pixels.
pub device_tile_size: u32,
}
/// Decomposes an image that is repeated into an image per individual repetition.
@@ -64,17 +64,17 @@ pub fn decompose_image(info: &TiledImage
if let Some(row_rect) = row_rect {
decompose_row(&row_rect, info, callback);
}
}
}
-fn decompose_row(item_rect: &LayerRect, info: &TiledImageInfo, callback: &mut FnMut(&DecomposedTile)) {
+fn decompose_row(item_rect: &LayoutRect, info: &TiledImageInfo, callback: &mut FnMut(&DecomposedTile)) {
let no_horizontal_tiling = info.device_image_size.width <= info.device_tile_size;
let no_horizontal_spacing = info.tile_spacing.width == 0.0;
if no_horizontal_tiling && no_horizontal_spacing {
decompose_cache_tiles(item_rect, info, callback);
return;
}
@@ -93,17 +93,17 @@ fn decompose_row(item_rect: &LayerRect,
if let Some(decomposed_rect) = decomposed_rect {
decompose_cache_tiles(&decomposed_rect, info, callback);
}
}
}
fn decompose_cache_tiles(
- item_rect: &LayerRect,
+ item_rect: &LayoutRect,
info: &TiledImageInfo,
callback: &mut FnMut(&DecomposedTile),
) {
// The image resource is tiled. We have to generate an image primitive
// for each tile.
// We need to do this because the image is broken up into smaller tiles in the texture
// cache and the image shader is not able to work with this type of sparse representation.
@@ -150,17 +150,17 @@ fn decompose_cache_tiles(
let num_tiles_x = (info.device_image_size.width / info.device_tile_size) as u16;
let num_tiles_y = (info.device_image_size.height / info.device_tile_size) as u16;
// Ratio between (image space) tile size and image size.
let img_dw = tile_size_f32 / (info.device_image_size.width as f32);
let img_dh = tile_size_f32 / (info.device_image_size.height as f32);
// Stretched size of the tile in layout space.
- let stretched_tile_size = LayerSize::new(
+ let stretched_tile_size = LayoutSize::new(
img_dw * info.stretch_size.width,
img_dh * info.stretch_size.height,
);
// The size in pixels of the tiles on the right and bottom edges, smaller
// than the regular tile size if the image is not a multiple of the tile size.
// Zero means the image size is a multiple of the tile size.
let leftover = DeviceUintSize::new(
@@ -223,41 +223,41 @@ fn decompose_cache_tiles(
shader_repeat_y,
callback,
);
}
}
}
fn add_device_tile(
- item_rect: &LayerRect,
- stretched_tile_size: LayerSize,
+ item_rect: &LayoutRect,
+ stretched_tile_size: LayoutSize,
tile_offset: TileOffset,
tile_ratio_width: f32,
tile_ratio_height: f32,
shader_repeat_x: bool,
shader_repeat_y: bool,
callback: &mut FnMut(&DecomposedTile),
) {
// If the image is tiled along a given axis, we can't have the shader compute
// the image repetition pattern. In this case we base the primitive's rectangle size
// on the stretched tile size which effectively cancels the repetition (and repetition
// has to be emulated by generating more primitives).
// If the image is not tiled along this axis, we can perform the repetition in the
// shader. In this case we use the item's size in the primitive (on that particular
// axis).
// See the shader_repeat_x/y code below.
- let stretch_size = LayerSize::new(
+ let stretch_size = LayoutSize::new(
stretched_tile_size.width * tile_ratio_width,
stretched_tile_size.height * tile_ratio_height,
);
- let mut prim_rect = LayerRect::new(
- item_rect.origin + LayerVector2D::new(
+ let mut prim_rect = LayoutRect::new(
+ item_rect.origin + LayoutVector2D::new(
tile_offset.x as f32 * stretched_tile_size.width,
tile_offset.y as f32 * stretched_tile_size.height,
),
stretch_size,
);
if shader_repeat_x {
assert_eq!(tile_offset.x, 0);
--- a/gfx/webrender/src/picture.rs
+++ b/gfx/webrender/src/picture.rs
@@ -1,14 +1,14 @@
/* 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 api::{FilterOp, MixBlendMode, PipelineId, PremultipliedColorF};
-use api::{DeviceIntRect, DeviceIntSize, LayerRect};
+use api::{DeviceIntRect, DeviceIntSize, LayoutRect};
use api::{PictureIntPoint, PictureIntRect, PictureIntSize};
use box_shadow::{BLUR_SAMPLE_SCALE};
use clip_scroll_tree::ClipScrollNodeIndex;
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState};
use gpu_cache::{GpuCacheHandle};
use prim_store::{PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
use prim_store::{PrimitiveMetadata, ScrollNodeAndClipChain};
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle};
@@ -146,17 +146,17 @@ pub struct PicturePrimitive {
// If requested as a frame output (for rendering
// pages to a texture), this is the pipeline this
// picture is the root of.
pub frame_output_pipeline_id: Option<PipelineId>,
// The original reference frame ID for this picture.
// It is only different if this is part of a 3D
// rendering context.
pub reference_frame_index: ClipScrollNodeIndex,
- pub real_local_rect: LayerRect,
+ pub real_local_rect: LayoutRect,
// An optional cache handle for storing extra data
// in the GPU cache, depending on the type of
// picture.
pub extra_gpu_data_handle: GpuCacheHandle,
// Unique identifier for this picture.
pub id: PictureId,
}
@@ -190,17 +190,17 @@ impl PicturePrimitive {
PicturePrimitive {
runs: Vec::new(),
surface: None,
secondary_render_task_id: None,
composite_mode,
is_in_3d_context,
frame_output_pipeline_id,
reference_frame_index,
- real_local_rect: LayerRect::zero(),
+ real_local_rect: LayoutRect::zero(),
extra_gpu_data_handle: GpuCacheHandle::new(),
apply_local_clip_rect,
pipeline_id,
task_rect: DeviceIntRect::zero(),
id,
}
}
@@ -222,17 +222,17 @@ impl PicturePrimitive {
count: 1,
clip_and_scroll,
});
}
pub fn update_local_rect(
&mut self,
prim_run_rect: PrimitiveRunLocalRect,
- ) -> LayerRect {
+ ) -> LayoutRect {
let local_content_rect = prim_run_rect.local_rect_in_actual_parent_space;
self.real_local_rect = prim_run_rect.local_rect_in_original_parent_space;
match self.composite_mode {
Some(PictureCompositeMode::Filter(FilterOp::Blur(blur_radius))) => {
let inflate_size = (blur_radius * BLUR_SAMPLE_SCALE).ceil();
local_content_rect.inflate(inflate_size, inflate_size)
@@ -267,16 +267,21 @@ impl PicturePrimitive {
false
}
None => {
true
}
}
}
+ // Disallow subpixel AA if an intermediate surface is needed.
+ pub fn allow_subpixel_aa(&self) -> bool {
+ self.can_draw_directly_to_parent_surface()
+ }
+
pub fn prepare_for_render_inner(
&mut self,
prim_index: PrimitiveIndex,
prim_metadata: &mut PrimitiveMetadata,
mut pic_state_for_children: PictureState,
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -1,17 +1,17 @@
/* 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 api::{AlphaType, BorderRadius, BoxShadowClipMode, BuiltDisplayList, ClipMode, ColorF, ComplexClipRegion};
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode};
use api::{FilterOp, GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
-use api::{GlyphRasterSpace, LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D};
-use api::{PipelineId, PremultipliedColorF, Shadow, YuvColorSpace, YuvFormat};
+use api::{GlyphRasterSpace, LayoutPoint, LayoutRect, LayoutSize, LayoutToWorldTransform, LayoutVector2D};
+use api::{PipelineId, PremultipliedColorF, PropertyBinding, Shadow, YuvColorSpace, YuvFormat};
use border::{BorderCornerInstance, BorderEdgeKind};
use box_shadow::BLUR_SAMPLE_SCALE;
use clip_scroll_tree::{ClipChainIndex, ClipScrollNodeIndex, CoordinateSystemId};
use clip_scroll_node::ClipScrollNode;
use clip::{ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipSource};
use clip::{ClipSourcesHandle, ClipWorkItem};
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
use frame_builder::PrimitiveRunContext;
@@ -21,20 +21,21 @@ use gpu_cache::{GpuBlockData, GpuCache,
use gpu_types::{ClipChainRectIndex};
use picture::{PictureCompositeMode, PictureId, PicturePrimitive};
#[cfg(debug_assertions)]
use render_backend::FrameId;
use render_task::{BlitSource, RenderTask, RenderTaskCacheKey};
use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskCacheEntryHandle};
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
use resource_cache::{ImageProperties, ImageRequest};
+use scene::SceneProperties;
use segment::SegmentBuilder;
use std::{mem, usize};
use std::sync::Arc;
-use util::{MatrixHelpers, WorldToLayerFastTransform, calculate_screen_bounding_rect};
+use util::{MatrixHelpers, WorldToLayoutFastTransform, calculate_screen_bounding_rect};
use util::{pack_as_float, recycle_vec};
const MIN_BRUSH_SPLIT_AREA: f32 = 256.0 * 256.0;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ScrollNodeAndClipChain {
pub scroll_node_id: ClipScrollNodeIndex,
@@ -105,18 +106,18 @@ impl CachedGradient {
// for the primitive, to enable the plane splitting
// logic to work correctly.
// TODO(gw) In the future, we can probably simplify
// this - perhaps calculate the world space
// polygons directly and store internally
// in the picture structure.
#[derive(Debug)]
pub struct PrimitiveRunLocalRect {
- pub local_rect_in_actual_parent_space: LayerRect,
- pub local_rect_in_original_parent_space: LayerRect,
+ pub local_rect_in_actual_parent_space: LayoutRect,
+ pub local_rect_in_original_parent_space: LayoutRect,
}
/// For external images, it's not possible to know the
/// UV coords of the image (or the image data itself)
/// until the render thread receives the frame and issues
/// callbacks to the client application. For external
/// images that are visible, a DeferredResolve is created
/// that is stored in the frame. This allows the render
@@ -179,73 +180,116 @@ pub struct PrimitiveMetadata {
pub prim_kind: PrimitiveKind,
pub cpu_prim_index: SpecificPrimitiveIndex,
pub gpu_location: GpuCacheHandle,
pub clip_task_id: Option<RenderTaskId>,
// TODO(gw): In the future, we should just pull these
// directly from the DL item, instead of
// storing them here.
- pub local_rect: LayerRect,
- pub local_clip_rect: LayerRect,
+ pub local_rect: LayoutRect,
+ pub local_clip_rect: LayoutRect,
pub clip_chain_rect_index: ClipChainRectIndex,
pub is_backface_visible: bool,
pub screen_rect: Option<ScreenRect>,
/// A tag used to identify this primitive outside of WebRender. This is
/// used for returning useful data during hit testing.
pub tag: Option<ItemTag>,
/// The last frame ID (of the `RenderTaskTree`) this primitive
/// was prepared for rendering in.
#[cfg(debug_assertions)]
pub prepared_frame_id: FrameId,
}
+// Maintains a list of opacity bindings that have been collapsed into
+// the color of a single primitive. This is an important optimization
+// that avoids allocating an intermediate surface for most common
+// uses of opacity filters.
+#[derive(Debug)]
+pub struct OpacityBinding {
+ bindings: Vec<PropertyBinding<f32>>,
+ current: f32,
+}
+
+impl OpacityBinding {
+ pub fn new() -> OpacityBinding {
+ OpacityBinding {
+ bindings: Vec::new(),
+ current: 1.0,
+ }
+ }
+
+ // Add a new opacity value / binding to the list
+ pub fn push(&mut self, binding: PropertyBinding<f32>) {
+ self.bindings.push(binding);
+ }
+
+ // Resolve the current value of each opacity binding, and
+ // store that as a single combined opacity. Returns true
+ // if the opacity value changed from last time.
+ pub fn update(&mut self, scene_properties: &SceneProperties) -> bool {
+ let mut new_opacity = 1.0;
+
+ for binding in &self.bindings {
+ let opacity = scene_properties.resolve_float(binding, 1.0);
+ new_opacity = new_opacity * opacity;
+ }
+
+ let changed = new_opacity != self.current;
+ self.current = new_opacity;
+
+ changed
+ }
+}
+
#[derive(Debug)]
pub enum BrushKind {
Solid {
color: ColorF,
+ opacity_binding: OpacityBinding,
},
Clear,
Picture {
pic_index: PictureIndex,
},
Image {
request: ImageRequest,
current_epoch: Epoch,
alpha_type: AlphaType,
- stretch_size: LayerSize,
- tile_spacing: LayerSize,
+ stretch_size: LayoutSize,
+ tile_spacing: LayoutSize,
source: ImageSource,
sub_rect: Option<DeviceIntRect>,
+ opacity_binding: OpacityBinding,
},
YuvImage {
yuv_key: [ImageKey; 3],
format: YuvFormat,
color_space: YuvColorSpace,
image_rendering: ImageRendering,
},
RadialGradient {
gradient_index: CachedGradientIndex,
stops_range: ItemRange<GradientStop>,
extend_mode: ExtendMode,
- center: LayerPoint,
+ center: LayoutPoint,
start_radius: f32,
end_radius: f32,
ratio_xy: f32,
},
LinearGradient {
gradient_index: CachedGradientIndex,
stops_range: ItemRange<GradientStop>,
stops_count: usize,
extend_mode: ExtendMode,
reverse_stops: bool,
- start_point: LayerPoint,
- end_point: LayerPoint,
+ start_point: LayoutPoint,
+ end_point: LayoutPoint,
}
}
impl BrushKind {
fn supports_segments(&self) -> bool {
match *self {
BrushKind::Solid { .. } |
BrushKind::Image { .. } |
@@ -255,16 +299,24 @@ impl BrushKind {
// TODO(gw): Allow batch.rs to add segment instances
// for Picture primitives.
BrushKind::Picture { .. } => false,
BrushKind::Clear => false,
}
}
+
+ // Construct a brush that is a solid color rectangle.
+ pub fn new_solid(color: ColorF) -> BrushKind {
+ BrushKind::Solid {
+ color,
+ opacity_binding: OpacityBinding::new(),
+ }
+ }
}
bitflags! {
/// Each bit of the edge AA mask is:
/// 0, when the edge of the primitive needs to be considered for AA
/// 1, when the edge of the segment needs to be considered for AA
///
/// *Note*: the bit values have to match the shader logic in
@@ -274,31 +326,31 @@ bitflags! {
const TOP = 0x2;
const RIGHT = 0x4;
const BOTTOM = 0x8;
}
}
#[derive(Debug)]
pub struct BrushSegment {
- pub local_rect: LayerRect,
+ pub local_rect: LayoutRect,
pub clip_task_id: Option<RenderTaskId>,
pub may_need_clip_mask: bool,
pub edge_flags: EdgeAaSegmentMask,
}
impl BrushSegment {
pub fn new(
- origin: LayerPoint,
- size: LayerSize,
+ origin: LayoutPoint,
+ size: LayoutSize,
may_need_clip_mask: bool,
edge_flags: EdgeAaSegmentMask,
) -> BrushSegment {
BrushSegment {
- local_rect: LayerRect::new(origin, size),
+ local_rect: LayoutRect::new(origin, size),
clip_task_id: None,
may_need_clip_mask,
edge_flags,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -342,25 +394,29 @@ impl BrushPrimitive {
fn write_gpu_blocks(
&self,
request: &mut GpuDataRequest,
) {
// has to match VECS_PER_SPECIFIC_BRUSH
match self.kind {
BrushKind::YuvImage { .. } => {}
-
- BrushKind::Picture { .. } |
- BrushKind::Image { .. } => {
+ BrushKind::Picture { .. } => {
request.push(PremultipliedColorF::WHITE);
request.push(PremultipliedColorF::WHITE);
}
-
- BrushKind::Solid { color } => {
- request.push(color.premultiplied());
+ // Images are drawn as a white color, modulated by the total
+ // opacity coming from any collapsed property bindings.
+ BrushKind::Image { ref opacity_binding, .. } => {
+ request.push(ColorF::new(1.0, 1.0, 1.0, opacity_binding.current).premultiplied());
+ request.push(PremultipliedColorF::WHITE);
+ }
+ // Solid rects also support opacity collapsing.
+ BrushKind::Solid { color, ref opacity_binding, .. } => {
+ request.push(color.scale_alpha(opacity_binding.current).premultiplied());
}
BrushKind::Clear => {
// Opaque black with operator dest out
request.push(PremultipliedColorF::BLACK);
}
BrushKind::LinearGradient { start_point, end_point, extend_mode, .. } => {
request.push([
start_point.x,
@@ -413,19 +469,19 @@ pub enum ImageSource {
Cache {
size: DeviceIntSize,
handle: Option<RenderTaskCacheEntryHandle>,
},
}
#[derive(Debug)]
pub struct ImagePrimitiveCpu {
- pub tile_spacing: LayerSize,
+ pub tile_spacing: LayoutSize,
pub alpha_type: AlphaType,
- pub stretch_size: LayerSize,
+ pub stretch_size: LayoutSize,
pub current_epoch: Epoch,
pub source: ImageSource,
pub key: ImageCacheKey,
}
impl ToGpuBlocks for ImagePrimitiveCpu {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
request.push([
@@ -629,29 +685,29 @@ impl<'a> GradientGpuBlockBuilder<'a> {
request.push(entry.end_color);
}
}
}
#[derive(Debug, Clone)]
pub struct TextRunPrimitiveCpu {
pub font: FontInstance,
- pub offset: LayerVector2D,
+ pub offset: LayoutVector2D,
pub glyph_range: ItemRange<GlyphInstance>,
pub glyph_keys: Vec<GlyphKey>,
pub glyph_gpu_blocks: Vec<GpuBlockData>,
pub shadow: bool,
pub glyph_raster_space: GlyphRasterSpace,
}
impl TextRunPrimitiveCpu {
pub fn get_font(
&self,
device_pixel_scale: DevicePixelScale,
- transform: Option<LayerToWorldTransform>,
+ transform: Option<LayoutToWorldTransform>,
) -> FontInstance {
let mut font = self.font.clone();
font.size = font.size.scale_by(device_pixel_scale.0);
if let Some(transform) = transform {
if transform.has_perspective_component() ||
!transform.has_2d_inverse() ||
self.glyph_raster_space != GlyphRasterSpace::Screen {
font.render_mode = font.render_mode.limit_by(FontRenderMode::Alpha);
@@ -660,20 +716,25 @@ impl TextRunPrimitiveCpu {
}
}
font
}
fn prepare_for_render(
&mut self,
device_pixel_scale: DevicePixelScale,
- transform: Option<LayerToWorldTransform>,
+ transform: Option<LayoutToWorldTransform>,
+ allow_subpixel_aa: bool,
display_list: &BuiltDisplayList,
frame_building_state: &mut FrameBuildingState,
) {
+ if !allow_subpixel_aa {
+ self.font.render_mode = self.font.render_mode.limit_by(FontRenderMode::Alpha);
+ }
+
let font = self.get_font(device_pixel_scale, transform);
// Cache the glyph positions, if not in the cache already.
// TODO(gw): In the future, remove `glyph_instances`
// completely, and just reference the glyphs
// directly from the display list.
if self.glyph_keys.is_empty() {
let subpx_dir = font.subpx_dir.limit_by(font.render_mode);
@@ -729,24 +790,24 @@ impl TextRunPrimitiveCpu {
assert!(request.current_used_block_num() <= MAX_VERTEX_TEXTURE_WIDTH);
}
}
#[derive(Debug)]
#[repr(C)]
struct ClipRect {
- rect: LayerRect,
+ rect: LayoutRect,
mode: f32,
}
#[derive(Debug)]
#[repr(C)]
struct ClipCorner {
- rect: LayerRect,
+ rect: LayoutRect,
outer_radius_x: f32,
outer_radius_y: f32,
inner_radius_x: f32,
inner_radius_y: f32,
}
impl ToGpuBlocks for ClipCorner {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
@@ -760,31 +821,31 @@ impl ClipCorner {
request.push([
self.outer_radius_x,
self.outer_radius_y,
self.inner_radius_x,
self.inner_radius_y,
]);
}
- fn uniform(rect: LayerRect, outer_radius: f32, inner_radius: f32) -> ClipCorner {
+ fn uniform(rect: LayoutRect, outer_radius: f32, inner_radius: f32) -> ClipCorner {
ClipCorner {
rect,
outer_radius_x: outer_radius,
outer_radius_y: outer_radius,
inner_radius_x: inner_radius,
inner_radius_y: inner_radius,
}
}
}
#[derive(Debug)]
#[repr(C)]
pub struct ImageMaskData {
- pub local_rect: LayerRect,
+ pub local_rect: LayoutRect,
}
impl ToGpuBlocks for ImageMaskData {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
request.push(self.local_rect);
}
}
@@ -793,111 +854,111 @@ pub struct ClipData {
rect: ClipRect,
top_left: ClipCorner,
top_right: ClipCorner,
bottom_left: ClipCorner,
bottom_right: ClipCorner,
}
impl ClipData {
- pub fn rounded_rect(rect: &LayerRect, radii: &BorderRadius, mode: ClipMode) -> ClipData {
+ pub fn rounded_rect(rect: &LayoutRect, radii: &BorderRadius, mode: ClipMode) -> ClipData {
ClipData {
rect: ClipRect {
rect: *rect,
mode: mode as u32 as f32,
},
top_left: ClipCorner {
- rect: LayerRect::new(
- LayerPoint::new(rect.origin.x, rect.origin.y),
- LayerSize::new(radii.top_left.width, radii.top_left.height),
+ rect: LayoutRect::new(
+ LayoutPoint::new(rect.origin.x, rect.origin.y),
+ LayoutSize::new(radii.top_left.width, radii.top_left.height),
),
outer_radius_x: radii.top_left.width,
outer_radius_y: radii.top_left.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
top_right: ClipCorner {
- rect: LayerRect::new(
- LayerPoint::new(
+ rect: LayoutRect::new(
+ LayoutPoint::new(
rect.origin.x + rect.size.width - radii.top_right.width,
rect.origin.y,
),
- LayerSize::new(radii.top_right.width, radii.top_right.height),
+ LayoutSize::new(radii.top_right.width, radii.top_right.height),
),
outer_radius_x: radii.top_right.width,
outer_radius_y: radii.top_right.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
bottom_left: ClipCorner {
- rect: LayerRect::new(
- LayerPoint::new(
+ rect: LayoutRect::new(
+ LayoutPoint::new(
rect.origin.x,
rect.origin.y + rect.size.height - radii.bottom_left.height,
),
- LayerSize::new(radii.bottom_left.width, radii.bottom_left.height),
+ LayoutSize::new(radii.bottom_left.width, radii.bottom_left.height),
),
outer_radius_x: radii.bottom_left.width,
outer_radius_y: radii.bottom_left.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
bottom_right: ClipCorner {
- rect: LayerRect::new(
- LayerPoint::new(
+ rect: LayoutRect::new(
+ LayoutPoint::new(
rect.origin.x + rect.size.width - radii.bottom_right.width,
rect.origin.y + rect.size.height - radii.bottom_right.height,
),
- LayerSize::new(radii.bottom_right.width, radii.bottom_right.height),
+ LayoutSize::new(radii.bottom_right.width, radii.bottom_right.height),
),
outer_radius_x: radii.bottom_right.width,
outer_radius_y: radii.bottom_right.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
}
}
- pub fn uniform(rect: LayerRect, radius: f32, mode: ClipMode) -> ClipData {
+ pub fn uniform(rect: LayoutRect, radius: f32, mode: ClipMode) -> ClipData {
ClipData {
rect: ClipRect {
rect,
mode: mode as u32 as f32,
},
top_left: ClipCorner::uniform(
- LayerRect::new(
- LayerPoint::new(rect.origin.x, rect.origin.y),
- LayerSize::new(radius, radius),
+ LayoutRect::new(
+ LayoutPoint::new(rect.origin.x, rect.origin.y),
+ LayoutSize::new(radius, radius),
),
radius,
0.0,
),
top_right: ClipCorner::uniform(
- LayerRect::new(
- LayerPoint::new(rect.origin.x + rect.size.width - radius, rect.origin.y),
- LayerSize::new(radius, radius),
+ LayoutRect::new(
+ LayoutPoint::new(rect.origin.x + rect.size.width - radius, rect.origin.y),
+ LayoutSize::new(radius, radius),
),
radius,
0.0,
),
bottom_left: ClipCorner::uniform(
- LayerRect::new(
- LayerPoint::new(rect.origin.x, rect.origin.y + rect.size.height - radius),
- LayerSize::new(radius, radius),
+ LayoutRect::new(
+ LayoutPoint::new(rect.origin.x, rect.origin.y + rect.size.height - radius),
+ LayoutSize::new(radius, radius),
),
radius,
0.0,
),
bottom_right: ClipCorner::uniform(
- LayerRect::new(
- LayerPoint::new(
+ LayoutRect::new(
+ LayoutPoint::new(
rect.origin.x + rect.size.width - radius,
rect.origin.y + rect.size.height - radius,
),
- LayerSize::new(radius, radius),
+ LayoutSize::new(radius, radius),
),
radius,
0.0,
),
}
}
pub fn write(&self, request: &mut GpuDataRequest) {
@@ -932,17 +993,17 @@ impl PrimitiveContainer {
// primitive types to use this.
pub fn is_visible(&self) -> bool {
match *self {
PrimitiveContainer::TextRun(ref info) => {
info.font.color.a > 0
}
PrimitiveContainer::Brush(ref brush) => {
match brush.kind {
- BrushKind::Solid { ref color } => {
+ BrushKind::Solid { ref color, .. } => {
color.a > 0.0
}
BrushKind::Clear |
BrushKind::Picture { .. } |
BrushKind::Image { .. } |
BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } |
BrushKind::LinearGradient { .. } => {
@@ -982,19 +1043,17 @@ impl PrimitiveContainer {
shadow: true,
glyph_raster_space: info.glyph_raster_space,
})
}
PrimitiveContainer::Brush(ref brush) => {
match brush.kind {
BrushKind::Solid { .. } => {
PrimitiveContainer::Brush(BrushPrimitive::new(
- BrushKind::Solid {
- color: shadow.color,
- },
+ BrushKind::new_solid(shadow.color),
None,
))
}
BrushKind::Clear |
BrushKind::Picture { .. } |
BrushKind::Image { .. } |
BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } |
@@ -1072,47 +1131,47 @@ impl PrimitiveStore {
let picture_index = PictureIndex(self.pictures.len());
self.pictures.push(picture);
self.next_picture_id += 1;
picture_index
}
pub fn add_primitive(
&mut self,
- local_rect: &LayerRect,
- local_clip_rect: &LayerRect,
+ local_rect: &LayoutRect,
+ local_clip_rect: &LayoutRect,
is_backface_visible: bool,
clip_sources: Option<ClipSourcesHandle>,
tag: Option<ItemTag>,
container: PrimitiveContainer,
) -> PrimitiveIndex {
let prim_index = self.cpu_metadata.len();
let base_metadata = PrimitiveMetadata {
clip_sources,
gpu_location: GpuCacheHandle::new(),
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
clip_chain_rect_index: ClipChainRectIndex(0),
- is_backface_visible: is_backface_visible,
+ is_backface_visible,
screen_rect: None,
tag,
opacity: PrimitiveOpacity::translucent(),
prim_kind: PrimitiveKind::Brush,
cpu_prim_index: SpecificPrimitiveIndex(0),
#[cfg(debug_assertions)]
prepared_frame_id: FrameId(0),
};
let metadata = match container {
PrimitiveContainer::Brush(brush) => {
let opacity = match brush.kind {
BrushKind::Clear => PrimitiveOpacity::translucent(),
- BrushKind::Solid { ref color } => PrimitiveOpacity::from_alpha(color.a),
+ BrushKind::Solid { ref color, .. } => PrimitiveOpacity::from_alpha(color.a),
BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
BrushKind::LinearGradient { .. } => PrimitiveOpacity::translucent(),
BrushKind::Picture { .. } => PrimitiveOpacity::translucent(),
};
let metadata = PrimitiveMetadata {
@@ -1161,16 +1220,131 @@ impl PrimitiveStore {
}
};
self.cpu_metadata.push(metadata);
PrimitiveIndex(prim_index)
}
+ // Internal method that retrieves the primitive index of a primitive
+ // that can be the target for collapsing parent opacity filters into.
+ fn get_opacity_collapse_prim(
+ &self,
+ pic_index: PictureIndex,
+ ) -> Option<PrimitiveIndex> {
+ let pic = &self.pictures[pic_index.0];
+
+ // We can only collapse opacity if there is a single primitive, otherwise
+ // the opacity needs to be applied to the primitives as a group.
+ if pic.runs.len() != 1 {
+ return None;
+ }
+
+ let run = &pic.runs[0];
+ if run.count != 1 {
+ return None;
+ }
+
+ let prim_metadata = &self.cpu_metadata[run.base_prim_index.0];
+
+ // For now, we only support opacity collapse on solid rects and images.
+ // This covers the most common types of opacity filters that can be
+ // handled by this optimization. In the future, we can easily extend
+ // this to other primitives, such as text runs and gradients.
+ match prim_metadata.prim_kind {
+ PrimitiveKind::Brush => {
+ let brush = &self.cpu_brushes[prim_metadata.cpu_prim_index.0];
+ match brush.kind {
+ BrushKind::Picture { pic_index, .. } => {
+ let pic = &self.pictures[pic_index.0];
+ // If we encounter a picture that is a pass-through
+ // (i.e. no composite mode), then we can recurse into
+ // that to try and find a primitive to collapse to.
+ if pic.composite_mode.is_none() {
+ return self.get_opacity_collapse_prim(pic_index);
+ }
+ }
+ // If we find a single rect or image, we can use that
+ // as the primitive to collapse the opacity into.
+ BrushKind::Solid { .. } | BrushKind::Image { .. } => {
+ return Some(run.base_prim_index)
+ }
+ BrushKind::YuvImage { .. } |
+ BrushKind::LinearGradient { .. } |
+ BrushKind::RadialGradient { .. } |
+ BrushKind::Clear => {}
+ }
+ }
+ PrimitiveKind::TextRun |
+ PrimitiveKind::Image |
+ PrimitiveKind::Border => {}
+ }
+
+ None
+ }
+
+ // Apply any optimizations to drawing this picture. Currently,
+ // we just support collapsing pictures with an opacity filter
+ // by pushing that opacity value into the color of a primitive
+ // if that picture contains one compatible primitive.
+ pub fn optimize_picture_if_possible(
+ &mut self,
+ pic_index: PictureIndex,
+ ) {
+ // Only handle opacity filters for now.
+ let binding = match self.pictures[pic_index.0].composite_mode {
+ Some(PictureCompositeMode::Filter(FilterOp::Opacity(binding, _))) => {
+ binding
+ }
+ _ => {
+ return;
+ }
+ };
+
+ // See if this picture contains a single primitive that supports
+ // opacity collapse.
+ if let Some(prim_index) = self.get_opacity_collapse_prim(pic_index) {
+ let prim_metadata = &self.cpu_metadata[prim_index.0];
+ match prim_metadata.prim_kind {
+ PrimitiveKind::Brush => {
+ let brush = &mut self.cpu_brushes[prim_metadata.cpu_prim_index.0];
+
+ // By this point, we know we should only have found a primitive
+ // that supports opacity collapse.
+ match brush.kind {
+ BrushKind::Solid { ref mut opacity_binding, .. } |
+ BrushKind::Image { ref mut opacity_binding, .. } => {
+ opacity_binding.push(binding);
+ }
+ BrushKind::Clear { .. } |
+ BrushKind::Picture { .. } |
+ BrushKind::YuvImage { .. } |
+ BrushKind::LinearGradient { .. } |
+ BrushKind::RadialGradient { .. } => {
+ unreachable!("bug: invalid prim type for opacity collapse");
+ }
+ };
+ }
+ PrimitiveKind::TextRun |
+ PrimitiveKind::Image |
+ PrimitiveKind::Border => {
+ unreachable!("bug: invalid prim type for opacity collapse");
+ }
+ }
+
+ // The opacity filter has been collapsed, so mark this picture
+ // as a pass though. This means it will no longer allocate an
+ // intermediate surface or incur an extra blend / blit. Instead,
+ // the collapsed primitive will be drawn directly into the
+ // parent picture.
+ self.pictures[pic_index.0].composite_mode = None;
+ }
+ }
+
pub fn get_metadata(&self, index: PrimitiveIndex) -> &PrimitiveMetadata {
&self.cpu_metadata[index.0]
}
pub fn prim_count(&self) -> usize {
self.cpu_metadata.len()
}
@@ -1194,16 +1368,17 @@ impl PrimitiveStore {
PrimitiveKind::Border => {}
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 = Some(prim_run_context.scroll_node.world_content_transform.into());
text.prepare_for_render(
frame_context.device_pixel_scale,
transform,
+ pic_context.allow_subpixel_aa,
pic_context.display_list,
frame_state,
);
}
PrimitiveKind::Image => {
let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0];
let image_properties = frame_state
.resource_cache
@@ -1313,30 +1488,37 @@ impl PrimitiveStore {
);
}
}
}
PrimitiveKind::Brush => {
let brush = &mut self.cpu_brushes[metadata.cpu_prim_index.0];
match brush.kind {
- BrushKind::Image { request, sub_rect, ref mut current_epoch, ref mut source, .. } => {
+ BrushKind::Image { request, sub_rect, ref mut current_epoch, ref mut source, ref mut opacity_binding, .. } => {
let image_properties = frame_state
.resource_cache
.get_image_properties(request.key);
// Set if we need to request the source image from the cache this frame.
if let Some(image_properties) = image_properties {
- // See if this image has been updated since we last hit this code path.
- // If so, we need to update the opacity.
- if image_properties.epoch != *current_epoch {
- *current_epoch = image_properties.epoch;
- metadata.opacity.is_opaque = image_properties.descriptor.is_opaque;
+ *current_epoch = image_properties.epoch;
+
+ // If the opacity changed, invalidate the GPU cache so that
+ // the new color for this primitive gets uploaded.
+ if opacity_binding.update(frame_context.scene_properties) {
+ frame_state.gpu_cache.invalidate(&mut metadata.gpu_location);
}
+ // Update opacity for this primitive to ensure the correct
+ // batching parameters are used.
+ metadata.opacity.is_opaque =
+ image_properties.descriptor.is_opaque &&
+ opacity_binding.current == 1.0;
+
// Work out whether this image is a normal / simple type, or if
// we need to pre-render it to the render task cache.
if let Some(rect) = sub_rect {
*source = ImageSource::Cache {
// Size in device-pixels we need to allocate in render task cache.
size: rect.size,
handle: None,
};
@@ -1460,17 +1642,26 @@ impl PrimitiveStore {
prim_index,
metadata,
pic_state_for_children,
pic_state,
frame_context,
frame_state,
);
}
- BrushKind::Solid { .. } |
+ BrushKind::Solid { ref color, ref mut opacity_binding, .. } => {
+ // If the opacity changed, invalidate the GPU cache so that
+ // the new color for this primitive gets uploaded. Also update
+ // the opacity field that controls which batches this primitive
+ // will be added to.
+ if opacity_binding.update(frame_context.scene_properties) {
+ metadata.opacity = PrimitiveOpacity::from_alpha(opacity_binding.current * color.a);
+ frame_state.gpu_cache.invalidate(&mut metadata.gpu_location);
+ }
+ }
BrushKind::Clear => {}
}
}
}
// Mark this GPU resource as required for this frame.
if let Some(mut request) = frame_state.gpu_cache.request(&mut metadata.gpu_location) {
// has to match VECS_PER_BRUSH_PRIM
@@ -1626,17 +1817,17 @@ impl PrimitiveStore {
local_clip_rect
} else {
let clip_transform = frame_context
.node_data[clip_item.scroll_node_data_index.0 as usize]
.transform;
let prim_transform = &prim_run_context.scroll_node.world_content_transform;
let relative_transform = prim_transform
.inverse()
- .unwrap_or(WorldToLayerFastTransform::identity())
+ .unwrap_or(WorldToLayoutFastTransform::identity())
.pre_mul(&clip_transform.into());
relative_transform.transform_rect(&local_clip_rect)
};
segment_builder.push_clip_rect(local_clip_rect, radius, mode);
}
}
@@ -1803,17 +1994,17 @@ impl PrimitiveStore {
scroll_node_data_index: prim_run_context.scroll_node.node_data_index,
clip_sources: clip_sources.weak(),
coordinate_system_id: prim_coordinate_system_id,
},
// The local_clip_rect a property of ClipChain nodes that are ClipScrollNodes.
// It's used to calculate a local clipping rectangle before we reach this
// point, so we can set it to zero here. It should be unused from this point
// on.
- local_clip_rect: LayerRect::zero(),
+ local_clip_rect: LayoutRect::zero(),
screen_inner_rect,
screen_outer_rect: screen_outer_rect.unwrap_or(prim_screen_rect),
prev: None,
})
})
};
// If everything is clipped out, then we don't need to render this primitive.
@@ -1894,17 +2085,17 @@ impl PrimitiveStore {
pub fn prepare_prim_for_render(
&mut self,
prim_index: PrimitiveIndex,
prim_run_context: &PrimitiveRunContext,
pic_context: &PictureContext,
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
- ) -> Option<LayerRect> {
+ ) -> Option<LayoutRect> {
let mut may_need_clip_mask = true;
let mut pic_state_for_children = PictureState::new();
// Do some basic checks first, that can early out
// without even knowing the local rect.
let (prim_kind, cpu_prim_index) = {
let metadata = &self.cpu_metadata[prim_index.0];
@@ -1961,16 +2152,18 @@ impl PrimitiveStore {
PictureContext {
pipeline_id: pic.pipeline_id,
prim_runs: mem::replace(&mut pic.runs, Vec::new()),
original_reference_frame_index: Some(pic.reference_frame_index),
display_list,
inv_world_transform,
apply_local_clip_rect: pic.apply_local_clip_rect,
inflation_factor,
+ // TODO(lsalzman): allow overriding parent if intermediate surface is opaque
+ allow_subpixel_aa: pic_context.allow_subpixel_aa && pic.allow_subpixel_aa(),
}
};
let result = self.prepare_prim_runs(
&pic_context_for_children,
&mut pic_state_for_children,
frame_context,
frame_state,
@@ -2071,18 +2264,18 @@ impl PrimitiveStore {
pub fn prepare_prim_runs(
&mut self,
pic_context: &PictureContext,
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
) -> PrimitiveRunLocalRect {
let mut result = PrimitiveRunLocalRect {
- local_rect_in_actual_parent_space: LayerRect::zero(),
- local_rect_in_original_parent_space: LayerRect::zero(),
+ local_rect_in_actual_parent_space: LayoutRect::zero(),
+ local_rect_in_original_parent_space: LayoutRect::zero(),
};
for run in &pic_context.prim_runs {
// TODO(gw): Perhaps we can restructure this to not need to create
// a new primitive context for every run (if the hash
// lookups ever show up in a profile).
let scroll_node = &frame_context
.clip_scroll_tree
@@ -2233,27 +2426,27 @@ fn convert_clip_chain_to_clip_vector(
Some(node.work_item.clone())
})
.collect()
}
fn get_local_clip_rect_for_nodes(
scroll_node: &ClipScrollNode,
clip_chain: &ClipChain,
-) -> Option<LayerRect> {
+) -> Option<LayoutRect> {
let local_rect = ClipChainNodeIter { current: clip_chain.nodes.clone() }.fold(
None,
- |combined_local_clip_rect: Option<LayerRect>, node| {
+ |combined_local_clip_rect: Option<LayoutRect>, node| {
if node.work_item.coordinate_system_id != scroll_node.coordinate_system_id {
return combined_local_clip_rect;
}
Some(match combined_local_clip_rect {
Some(combined_rect) =>
- combined_rect.intersection(&node.local_clip_rect).unwrap_or_else(LayerRect::zero),
+ combined_rect.intersection(&node.local_clip_rect).unwrap_or_else(LayoutRect::zero),
None => node.local_clip_rect,
})
}
);
match local_rect {
Some(local_rect) => scroll_node.coordinate_system_relative_transform.unapply(&local_rect),
None => None,
@@ -2263,17 +2456,17 @@ fn get_local_clip_rect_for_nodes(
impl<'a> GpuDataRequest<'a> {
// Write the GPU cache data for an individual segment.
// TODO(gw): The second block is currently unused. In
// the future, it will be used to store a
// UV rect, allowing segments to reference
// part of an image.
fn write_segment(
&mut self,
- local_rect: LayerRect,
+ local_rect: LayoutRect,
) {
self.push(local_rect);
self.push([
1.0,
1.0,
0.0,
0.0
]);
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -2,17 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ApiMsg, BuiltDisplayList, ClearCache, DebugCommand};
#[cfg(feature = "debugger")]
use api::{BuiltDisplayListIter, SpecificDisplayItem};
use api::{DeviceIntPoint, DevicePixelScale, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
use api::{DocumentId, DocumentLayer, ExternalScrollId, FrameMsg, HitTestResult};
-use api::{IdNamespace, LayerPoint, PipelineId, RenderNotifier, SceneMsg, ScrollClamping};
+use api::{IdNamespace, LayoutPoint, PipelineId, RenderNotifier, SceneMsg, ScrollClamping};
use api::{ScrollLocation, ScrollNodeState, TransactionMsg, WorldPoint};
use api::channel::{MsgReceiver, Payload};
#[cfg(feature = "capture")]
use api::CaptureBits;
#[cfg(feature = "replay")]
use api::CapturedDocument;
use clip_scroll_tree::ClipScrollTree;
#[cfg(feature = "debugger")]
@@ -322,17 +322,17 @@ impl Document {
cursor: WorldPoint,
) -> bool {
self.clip_scroll_tree.scroll(scroll_location, cursor)
}
/// Returns true if the node actually changed position or false otherwise.
pub fn scroll_node(
&mut self,
- origin: LayerPoint,
+ origin: LayoutPoint,
id: ExternalScrollId,
clamp: ScrollClamping
) -> bool {
self.clip_scroll_tree.scroll_node(origin, id, clamp)
}
pub fn get_scroll_node_state(&self) -> Vec<ScrollNodeState> {
self.clip_scroll_tree.get_scroll_node_state()
@@ -726,32 +726,44 @@ impl RenderBackend {
if !transaction_msg.is_empty() {
self.update_document(
document_id,
transaction_msg,
&mut frame_counter,
&mut profile_counters
);
}
+ },
+ SceneBuilderResult::Stopped => {
+ panic!("We haven't sent a Stop yet, how did we get a Stopped back?");
}
}
}
keep_going = match self.api_rx.recv() {
Ok(msg) => {
if let Some(ref mut r) = self.recorder {
r.write_msg(frame_counter, &msg);
}
self.process_api_msg(msg, &mut profile_counters, &mut frame_counter)
}
Err(..) => { false }
};
}
let _ = self.scene_tx.send(SceneBuilderRequest::Stop);
+ // Ensure we read everything the scene builder is sending us from
+ // inflight messages, otherwise the scene builder might panic.
+ while let Ok(msg) = self.scene_rx.recv() {
+ match msg {
+ SceneBuilderResult::Stopped => break,
+ _ => continue,
+ }
+ }
+
self.notifier.shut_down();
if let Some(ref sampler) = self.sampler {
sampler.deregister();
}
}
@@ -1029,18 +1041,18 @@ impl RenderBackend {
pending_update,
profile_counters.clone()
);
self.result_tx.send(msg).unwrap();
profile_counters.reset();
doc.render_on_hittest = false;
}
- if op.render || op.scroll {
- self.notifier.new_document_ready(document_id, op.scroll, op.composite);
+ if transaction_msg.generate_frame {
+ self.notifier.new_frame_ready(document_id, op.scroll, op.composite);
}
}
#[cfg(not(feature = "debugger"))]
fn get_docs_for_debugger(&self) -> String {
String::new()
}
@@ -1323,14 +1335,14 @@ impl RenderBackend {
id,
render_doc,
self.resource_cache.pending_updates(),
profile_counters.clone(),
);
self.result_tx.send(msg_publish).unwrap();
profile_counters.reset();
- self.notifier.new_document_ready(id, false, true);
+ self.notifier.new_frame_ready(id, false, true);
self.documents.insert(id, doc);
}
}
}
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -11,33 +11,32 @@
use api::{BlobImageRenderer, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentId, Epoch, ExternalImageId};
use api::{ExternalImageType, FontRenderMode, FrameMsg, ImageFormat, PipelineId};
use api::{RenderApiSender, RenderNotifier, TexelRect, TextureTarget};
use api::{channel};
use api::DebugCommand;
use api::channel::PayloadReceiverHelperMethods;
-use batch::{BatchKey, BatchKind, BatchTextures, BrushBatchKind, TransformBatchKind};
+use batch::{BatchKind, BatchTextures, BrushBatchKind, TransformBatchKind};
#[cfg(any(feature = "capture", feature = "replay"))]
use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
use debug_colors;
use device::{DepthFunction, Device, FrameId, Program, UploadMethod, Texture, PBO};
use device::{ExternalTexture, FBOId, TextureSlot};
use device::{FileWatcherHandler, ShaderError, TextureFilter,
VertexUsageHint, VAO, VBO, CustomVAO};
use device::{ProgramCache, ReadPixelsFormat};
use euclid::{rect, Transform3D};
use frame_builder::FrameBuilderConfig;
use gleam::gl;
use glyph_rasterizer::{GlyphFormat, GlyphRasterizer};
use gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList};
#[cfg(feature = "pathfinder")]
use gpu_glyph_renderer::GpuGlyphRenderer;
-use gpu_types::PrimitiveInstance;
use internal_types::{SourceTexture, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
use internal_types::{CacheTextureId, DebugOutput, FastHashMap, RenderedDocument, ResultMsg};
use internal_types::{TextureUpdateList, TextureUpdateOp, TextureUpdateSource};
use internal_types::{RenderTargetInfo, SavedTargetIndex};
use prim_store::DeferredResolve;
use profiler::{BackendProfileCounters, FrameProfileCounters,
GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
use query::GpuProfiler;
@@ -263,17 +262,20 @@ fn flag_changed(before: DebugFlags, afte
if before & select != after & select {
Some(after.contains(select))
} else {
None
}
}
#[repr(C)]
+#[derive(Copy, Clone, Debug)]
pub enum ShaderColorMode {
+ FromRenderPassMode = 0,
+
Alpha = 1,
SubpixelConstantTextColor = 2,
SubpixelWithBgColorPass0 = 3,
SubpixelWithBgColorPass1 = 4,
SubpixelWithBgColorPass2 = 5,
SubpixelDualSource = 6,
Bitmap = 7,
ColorBitmap = 8,
@@ -426,16 +428,58 @@ pub(crate) mod desc {
VertexAttribute {
name: "aClipDataResourceAddress",
count: 4,
kind: VertexAttributeKind::U16,
},
],
};
+ pub const BORDER_CORNER_DASH_AND_DOT: VertexDescriptor = VertexDescriptor {
+ vertex_attributes: &[
+ VertexAttribute {
+ name: "aPosition",
+ count: 2,
+ kind: VertexAttributeKind::F32,
+ },
+ ],
+ instance_attributes: &[
+ VertexAttribute {
+ name: "aClipRenderTaskAddress",
+ count: 1,
+ kind: VertexAttributeKind::I32,
+ },
+ VertexAttribute {
+ name: "aScrollNodeId",
+ count: 1,
+ kind: VertexAttributeKind::I32,
+ },
+ VertexAttribute {
+ name: "aClipSegment",
+ count: 1,
+ kind: VertexAttributeKind::I32,
+ },
+ VertexAttribute {
+ name: "aClipDataResourceAddress",
+ count: 4,
+ kind: VertexAttributeKind::U16,
+ },
+ VertexAttribute {
+ name: "aDashOrDot0",
+ count: 4,
+ kind: VertexAttributeKind::F32,
+ },
+ VertexAttribute {
+ name: "aDashOrDot1",
+ count: 4,
+ kind: VertexAttributeKind::F32,
+ },
+ ],
+ };
+
pub const GPU_CACHE_UPDATE: VertexDescriptor = VertexDescriptor {
vertex_attributes: &[
VertexAttribute {
name: "aPosition",
count: 2,
kind: VertexAttributeKind::U16Norm,
},
VertexAttribute {
@@ -532,16 +576,17 @@ pub(crate) mod desc {
};
}
#[derive(Debug, Copy, Clone)]
pub(crate) enum VertexArrayKind {
Primitive,
Blur,
Clip,
+ DashAndDot,
VectorStencil,
VectorCover,
}
#[derive(Clone, Debug, PartialEq)]
pub enum GraphicsApi {
OpenGL,
}
@@ -1253,16 +1298,17 @@ impl LazyInitializedDebugRenderer {
}
}
}
pub struct RendererVAOs {
prim_vao: VAO,
blur_vao: VAO,
clip_vao: VAO,
+ dash_and_dot_vao: VAO,
}
/// The renderer is responsible for submitting to the GPU the work prepared by the
/// RenderBackend.
pub struct Renderer {
result_rx: Receiver<ResultMsg>,
debug_server: DebugServer,
pub device: Device,
@@ -1539,16 +1585,18 @@ impl Renderer {
device.update_vao_main_vertices(&prim_vao, &quad_vertices, VertexUsageHint::Static);
let gpu_glyph_renderer = try!(GpuGlyphRenderer::new(&mut device,
&prim_vao,
options.precache_shaders));
let blur_vao = device.create_vao_with_new_instances(&desc::BLUR, &prim_vao);
let clip_vao = device.create_vao_with_new_instances(&desc::CLIP, &prim_vao);
+ let dash_and_dot_vao =
+ device.create_vao_with_new_instances(&desc::BORDER_CORNER_DASH_AND_DOT, &prim_vao);
let texture_cache_upload_pbo = device.create_pbo();
let texture_resolver = SourceTextureResolver::new(&mut device);
let node_data_texture = VertexDataTexture::new(&mut device);
let local_clip_rects_texture = VertexDataTexture::new(&mut device);
let render_task_texture = VertexDataTexture::new(&mut device);
@@ -1691,16 +1739,17 @@ impl Renderer {
enable_clear_scissor: options.enable_clear_scissor,
last_time: 0,
gpu_profile,
gpu_glyph_renderer,
vaos: RendererVAOs {
prim_vao,
blur_vao,
clip_vao,
+ dash_and_dot_vao,
},
node_data_texture,
local_clip_rects_texture,
render_task_texture,
pipeline_info: PipelineInfo::default(),
dither_matrix_texture,
external_image_handler: None,
output_image_handler: None,
@@ -2606,58 +2655,16 @@ impl Renderer {
// Note: leaving the viewport unchanged, it's not a part of FBO state
self.device.bind_draw_target(render_target, None);
if scissor_rect.is_some() {
self.device.enable_scissor();
}
}
- fn submit_batch(
- &mut self,
- key: &BatchKey,
- instances: &[PrimitiveInstance],
- projection: &Transform3D<f32>,
- render_tasks: &RenderTaskTree,
- render_target: Option<(&Texture, i32)>,
- framebuffer_size: DeviceUintSize,
- stats: &mut RendererStats,
- scissor_rect: Option<DeviceIntRect>,
- ) {
- self.shaders
- .get(key)
- .bind(
- &mut self.device, projection,
- &mut self.renderer_errors,
- );
-
- // Handle special case readback for composites.
- if let BatchKind::Brush(BrushBatchKind::MixBlend { task_id, source_id, backdrop_id }) = key.kind {
- // composites can't be grouped together because
- // they may overlap and affect each other.
- debug_assert_eq!(instances.len(), 1);
- self.handle_readback_composite(
- render_target,
- framebuffer_size,
- scissor_rect,
- &render_tasks[source_id],
- &render_tasks[task_id],
- &render_tasks[backdrop_id],
- );
- }
-
- let _timer = self.gpu_profile.start_timer(key.kind.sampler_tag());
- self.draw_instanced_batch(
- instances,
- VertexArrayKind::Primitive,
- &key.textures,
- stats
- );
- }
-
fn handle_blits(
&mut self,
blits: &[BlitJob],
render_tasks: &RenderTaskTree,
) {
if blits.is_empty() {
return;
}
@@ -2842,186 +2849,134 @@ impl Renderer {
// Draw opaque batches front-to-back for maximum
// z-buffer efficiency!
for batch in alpha_batch_container
.opaque_batches
.iter()
.rev()
{
- self.submit_batch(
- &batch.key,
+ self.shaders
+ .get(&batch.key)
+ .bind(
+ &mut self.device, projection,
+ &mut self.renderer_errors,
+ );
+
+ let _timer = self.gpu_profile.start_timer(batch.key.kind.sampler_tag());
+ self.draw_instanced_batch(
&batch.instances,
- projection,
- render_tasks,
- render_target,
- target_size,
- stats,
- alpha_batch_container.target_rect,
+ VertexArrayKind::Primitive,
+ &batch.key.textures,
+ stats
);
}
if alpha_batch_container.target_rect.is_some() {
self.device.disable_scissor();
}
}
self.device.disable_depth_write();
self.gpu_profile.finish_sampler(opaque_sampler);
}
let _gl = self.gpu_profile.start_marker("alpha batches");
let transparent_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
- self.device.set_blend(false);
+ self.device.set_blend(true);
let mut prev_blend_mode = BlendMode::None;
for alpha_batch_container in &target.alpha_batch_containers {
if let Some(target_rect) = alpha_batch_container.target_rect {
self.device.enable_scissor();
self.device.set_scissor_rect(target_rect);
}
for batch in &alpha_batch_container.alpha_batches {
- match batch.key.kind {
- BatchKind::Transformable(transform_kind, TransformBatchKind::TextRun(glyph_format)) => {
- // Text run batches are handled by this special case branch.
- // In the case of subpixel text, we draw it as a two pass
- // effect, to ensure we can apply clip masks correctly.
- // In the future, there are several optimizations available:
- // 1) Use dual source blending where available (almost all recent hardware).
- // 2) Use frame buffer fetch where available (most modern hardware).
- // 3) Consider the old constant color blend method where no clip is applied.
- let _timer = self.gpu_profile.start_timer(GPU_TAG_PRIM_TEXT_RUN);
-
- self.device.set_blend(true);
- // bind the proper shader first
- match batch.key.blend_mode {
- BlendMode::SubpixelDualSource => &mut self.shaders.ps_text_run_dual_source,
- _ => &mut self.shaders.ps_text_run,
+ if batch.key.blend_mode != prev_blend_mode {
+ match batch.key.blend_mode {
+ BlendMode::None => {
+ unreachable!("bug: opaque blend in alpha pass");
+ }
+ BlendMode::Alpha => {
+ self.device.set_blend_mode_alpha();
+ }
+ BlendMode::PremultipliedAlpha => {
+ self.device.set_blend_mode_premultiplied_alpha();
+ }
+ BlendMode::PremultipliedDestOut => {
+ self.device.set_blend_mode_premultiplied_dest_out();
+ }
+ BlendMode::SubpixelDualSource => {
+ self.device.set_blend_mode_subpixel_dual_source();
+ }
+ BlendMode::SubpixelConstantTextColor(color) => {
+ self.device.set_blend_mode_subpixel_constant_text_color(color);
+ }
+ BlendMode::SubpixelWithBgColor => {
+ // Using the three pass "component alpha with font smoothing
+ // background color" rendering technique:
+ //
+ // /webrender/doc/text-rendering.md
+ //
+ self.device.set_blend_mode_subpixel_with_bg_color_pass0();
+ self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass0 as _);
}
- .get(glyph_format, transform_kind)
- .bind(
- &mut self.device,
- projection,
- &mut self.renderer_errors,
- );
-
- match batch.key.blend_mode {
- BlendMode::Alpha => panic!("Attempt to composite non-premultiplied text primitives."),
- BlendMode::PremultipliedAlpha => {
- self.device.set_blend_mode_premultiplied_alpha();
- self.device.switch_mode(ShaderColorMode::from(glyph_format) as _);
-
- self.draw_instanced_batch(
- &batch.instances,
- VertexArrayKind::Primitive,
- &batch.key.textures,
- stats,
- );
- }
- BlendMode::SubpixelDualSource => {
- self.device.set_blend_mode_subpixel_dual_source();
- self.device.switch_mode(ShaderColorMode::SubpixelDualSource as _);
-
- self.draw_instanced_batch(
- &batch.instances,
- VertexArrayKind::Primitive,
- &batch.key.textures,
- stats,
- );
- }
- BlendMode::SubpixelConstantTextColor(color) => {
- self.device.set_blend_mode_subpixel_constant_text_color(color);
- self.device.switch_mode(ShaderColorMode::SubpixelConstantTextColor as _);
-
- self.draw_instanced_batch(
- &batch.instances,
- VertexArrayKind::Primitive,
- &batch.key.textures,
- stats,
- );
- }
- BlendMode::SubpixelWithBgColor => {
- // Using the three pass "component alpha with font smoothing
- // background color" rendering technique:
- //
- // /webrender/doc/text-rendering.md
- //
- self.device.set_blend_mode_subpixel_with_bg_color_pass0();
- self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass0 as _);
-
- self.draw_instanced_batch(
- &batch.instances,
- VertexArrayKind::Primitive,
- &batch.key.textures,
- stats,
- );
-
- self.device.set_blend_mode_subpixel_with_bg_color_pass1();
- self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass1 as _);
-
- // When drawing the 2nd and 3rd passes, we know that the VAO, textures etc
- // are all set up from the previous draw_instanced_batch call,
- // so just issue a draw call here to avoid re-uploading the
- // instances and re-binding textures etc.
- self.device
- .draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
-
- self.device.set_blend_mode_subpixel_with_bg_color_pass2();
- self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass2 as _);
-
- self.device
- .draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
- }
- BlendMode::PremultipliedDestOut | BlendMode::None => {
- unreachable!("bug: bad blend mode for text");
- }
- }
-
- prev_blend_mode = BlendMode::None;
- self.device.set_blend(false);
}
- _ => {
- if batch.key.blend_mode != prev_blend_mode {
- match batch.key.blend_mode {
- BlendMode::None => {
- self.device.set_blend(false);
- }
- BlendMode::Alpha => {
- self.device.set_blend(true);
- self.device.set_blend_mode_alpha();
- }
- BlendMode::PremultipliedAlpha => {
- self.device.set_blend(true);
- self.device.set_blend_mode_premultiplied_alpha();
- }
- BlendMode::PremultipliedDestOut => {
- self.device.set_blend(true);
- self.device.set_blend_mode_premultiplied_dest_out();
- }
- BlendMode::SubpixelConstantTextColor(..) |
- BlendMode::SubpixelWithBgColor |
- BlendMode::SubpixelDualSource => {
- unreachable!("bug: subpx text handled earlier");
- }
- }
- prev_blend_mode = batch.key.blend_mode;
- }
-
- self.submit_batch(
- &batch.key,
- &batch.instances,
- projection,
- render_tasks,
- render_target,
- target_size,
- stats,
- alpha_batch_container.target_rect,
- );
- }
+ prev_blend_mode = batch.key.blend_mode;
+ }
+
+ self.shaders
+ .get(&batch.key)
+ .bind(
+ &mut self.device, projection,
+ &mut self.renderer_errors,
+ );
+
+ // Handle special case readback for composites.
+ if let BatchKind::Brush(BrushBatchKind::MixBlend { task_id, source_id, backdrop_id }) = batch.key.kind {
+ // composites can't be grouped together because
+ // they may overlap and affect each other.
+ debug_assert_eq!(batch.instances.len(), 1);
+ self.handle_readback_composite(
+ render_target,
+ target_size,
+ alpha_batch_container.target_rect,
+ &render_tasks[source_id],
+ &render_tasks[task_id],
+ &render_tasks[backdrop_id],
+ );
+ }
+
+ let _timer = self.gpu_profile.start_timer(batch.key.kind.sampler_tag());
+ self.draw_instanced_batch(
+ &batch.instances,
+ VertexArrayKind::Primitive,
+ &batch.key.textures,
+ stats
+ );
+
+ if batch.key.blend_mode == BlendMode::SubpixelWithBgColor {
+ self.device.set_blend_mode_subpixel_with_bg_color_pass1();
+ self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass1 as _);
+
+ // When drawing the 2nd and 3rd passes, we know that the VAO, textures etc
+ // are all set up from the previous draw_instanced_batch call,
+ // so just issue a draw call here to avoid re-uploading the
+ // instances and re-binding textures etc.
+ self.device
+ .draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
+
+ self.device.set_blend_mode_subpixel_with_bg_color_pass2();
+ self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass2 as _);
+
+ self.device
+ .draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
+
+ prev_blend_mode = BlendMode::None;
}
}
if alpha_batch_container.target_rect.is_some() {
self.device.disable_scissor();
}
}
@@ -3152,17 +3107,17 @@ impl Renderer {
// in regions below.
if !target.clip_batcher.border_clears.is_empty() {
let _gm2 = self.gpu_profile.start_marker("clip borders [clear]");
self.device.set_blend(false);
self.shaders.cs_clip_border
.bind(&mut self.device, projection, &mut self.renderer_errors);
self.draw_instanced_batch(
&target.clip_batcher.border_clears,
- VertexArrayKind::Clip,
+ VertexArrayKind::DashAndDot,
&BatchTextures::no_texture(),
stats,
);
}
// Draw any dots or dashes for border corners.
if !target.clip_batcher.borders.is_empty() {
let _gm2 = self.gpu_profile.start_marker("clip borders");
@@ -3171,17 +3126,17 @@ impl Renderer {
// The individual dots and dashes in a border never overlap, so using
// a max blend mode here is fine.
self.device.set_blend(true);
self.device.set_blend_mode_max();
self.shaders.cs_clip_border
.bind(&mut self.device, projection, &mut self.renderer_errors);
self.draw_instanced_batch(
&target.clip_batcher.borders,
- VertexArrayKind::Clip,
+ VertexArrayKind::DashAndDot,
&BatchTextures::no_texture(),
stats,
);
}
// switch to multiplicative blending
self.device.set_blend(true);
self.device.set_blend_mode_multiply();
@@ -3904,16 +3859,17 @@ impl Renderer {
self.node_data_texture.deinit(&mut self.device);
self.local_clip_rects_texture.deinit(&mut self.device);
self.render_task_texture.deinit(&mut self.device);
self.device.delete_pbo(self.texture_cache_upload_pbo);
self.texture_resolver.deinit(&mut self.device);
self.device.delete_vao(self.vaos.prim_vao);
self.device.delete_vao(self.vaos.clip_vao);
self.device.delete_vao(self.vaos.blur_vao);
+ self.device.delete_vao(self.vaos.dash_and_dot_vao);
#[cfg(feature = "debug_renderer")]
{
self.debug.deinit(&mut self.device);
}
for (_, target) in self.output_targets {
self.device.delete_fbo(target.fbo_id);
@@ -4496,25 +4452,27 @@ impl Renderer {
fn get_vao<'a>(vertex_array_kind: VertexArrayKind,
vaos: &'a RendererVAOs,
gpu_glyph_renderer: &'a GpuGlyphRenderer)
-> &'a VAO {
match vertex_array_kind {
VertexArrayKind::Primitive => &vaos.prim_vao,
VertexArrayKind::Clip => &vaos.clip_vao,
VertexArrayKind::Blur => &vaos.blur_vao,
+ VertexArrayKind::DashAndDot => &vaos.dash_and_dot_vao,
VertexArrayKind::VectorStencil => &gpu_glyph_renderer.vector_stencil_vao,
VertexArrayKind::VectorCover => &gpu_glyph_renderer.vector_cover_vao,
}
}
#[cfg(not(feature = "pathfinder"))]
fn get_vao<'a>(vertex_array_kind: VertexArrayKind,
vaos: &'a RendererVAOs,
_: &'a GpuGlyphRenderer)
-> &'a VAO {
match vertex_array_kind {
VertexArrayKind::Primitive => &vaos.prim_vao,
VertexArrayKind::Clip => &vaos.clip_vao,
VertexArrayKind::Blur => &vaos.blur_vao,
+ VertexArrayKind::DashAndDot => &vaos.dash_and_dot_vao,
VertexArrayKind::VectorStencil | VertexArrayKind::VectorCover => unreachable!(),
}
}
--- a/gfx/webrender/src/scene.rs
+++ b/gfx/webrender/src/scene.rs
@@ -1,13 +1,13 @@
/* 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 api::{BuiltDisplayList, ColorF, DynamicProperties, Epoch, LayerSize, LayoutSize};
+use api::{BuiltDisplayList, ColorF, DynamicProperties, Epoch, LayoutSize};
use api::{FilterOp, LayoutTransform, PipelineId, PropertyBinding, PropertyBindingId};
use api::{ItemRange, MixBlendMode, StackingContext};
use internal_types::FastHashMap;
use std::sync::Arc;
/// Stores a map of the animated property bindings for the current display list. These
/// can be used to animate the transform and/or opacity of a display list without
/// re-submitting the display list itself.
@@ -90,17 +90,17 @@ impl SceneProperties {
}
/// A representation of the layout within the display port for a given document or iframe.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub struct ScenePipeline {
pub pipeline_id: PipelineId,
- pub viewport_size: LayerSize,
+ pub viewport_size: LayoutSize,
pub content_size: LayoutSize,
pub background_color: Option<ColorF>,
pub display_list: BuiltDisplayList,
}
/// A complete representation of the layout bundling visible pipelines together.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
@@ -125,17 +125,17 @@ impl Scene {
}
pub fn set_display_list(
&mut self,
pipeline_id: PipelineId,
epoch: Epoch,
display_list: BuiltDisplayList,
background_color: Option<ColorF>,
- viewport_size: LayerSize,
+ viewport_size: LayoutSize,
content_size: LayoutSize,
) {
let new_pipeline = ScenePipeline {
pipeline_id,
viewport_size,
content_size,
background_color,
display_list,
--- a/gfx/webrender/src/scene_builder.rs
+++ b/gfx/webrender/src/scene_builder.rs
@@ -33,16 +33,17 @@ pub enum SceneBuilderResult {
Transaction {
document_id: DocumentId,
built_scene: Option<BuiltScene>,
resource_updates: ResourceUpdates,
frame_ops: Vec<FrameMsg>,
render: bool,
result_tx: Sender<SceneSwapResult>,
},
+ Stopped,
}
// Message from render backend to scene builder to indicate the
// scene swap was completed. We need a separate channel for this
// so that they don't get mixed with SceneBuilderRequest messages.
pub enum SceneSwapResult {
Complete,
Aborted,
@@ -165,14 +166,19 @@ impl SceneBuilder {
let _ = self.api_tx.send(ApiMsg::WakeUp);
// Block until the swap is done, then invoke the hook
let _ = result_rx.recv();
if let Some(ref hooks) = self.hooks {
hooks.post_scene_swap(pipeline_info);
}
}
- SceneBuilderRequest::Stop => { return false; }
+ SceneBuilderRequest::Stop => {
+ self.tx.send(SceneBuilderResult::Stopped).unwrap();
+ // We don't need to send a WakeUp to api_tx because we only
+ // get the Stop when the RenderBackend loop is exiting.
+ return false;
+ }
}
true
}
}
--- a/gfx/webrender/src/segment.rs
+++ b/gfx/webrender/src/segment.rs
@@ -1,30 +1,30 @@
/* 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 api::{BorderRadius, ClipMode, LayerPoint, LayerPointAu, LayerRect, LayerSize};
+use api::{BorderRadius, ClipMode, LayoutPoint, LayoutPointAu, LayoutRect, LayoutSize};
use app_units::Au;
use prim_store::EdgeAaSegmentMask;
use std::{cmp, usize};
use util::extract_inner_rect_safe;
bitflags! {
pub struct ItemFlags: u8 {
const X_ACTIVE = 0x1;
const Y_ACTIVE = 0x2;
const HAS_MASK = 0x4;
}
}
// The segment builder outputs a list of these segments.
#[derive(Debug, PartialEq)]
pub struct Segment {
- pub rect: LayerRect,
+ pub rect: LayoutRect,
pub has_mask: bool,
pub edge_flags: EdgeAaSegmentMask,
pub region_x: usize,
pub region_y: usize,
}
// The segment builder creates a list of x/y axis events
// that are used to build a segment list. Right now, we
@@ -138,24 +138,24 @@ impl Event {
items[self.item_index.0].flags.set(flag, is_active);
}
}
// An item that provides some kind of clip region (either
// a clip in/out rect, or a mask region).
#[derive(Debug)]
struct Item {
- rect: LayerRect,
+ rect: LayoutRect,
mode: Option<ClipMode>,
flags: ItemFlags,
}
impl Item {
fn new(
- rect: LayerRect,
+ rect: LayoutRect,
mode: Option<ClipMode>,
has_mask: bool,
) -> Item {
let flags = if has_mask {
ItemFlags::HAS_MASK
} else {
ItemFlags::empty()
};
@@ -169,27 +169,27 @@ impl Item {
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)]
struct ItemIndex(usize);
// The main public interface to the segment module.
pub struct SegmentBuilder {
items: Vec<Item>,
- inner_rect: Option<LayerRect>,
- bounding_rect: Option<LayerRect>,
+ inner_rect: Option<LayoutRect>,
+ bounding_rect: Option<LayoutRect>,
}
impl SegmentBuilder {
// Create a new segment builder, supplying the primitive
// local rect and associated local clip rect.
pub fn new(
- local_rect: LayerRect,
- inner_rect: Option<LayerRect>,
- local_clip_rect: LayerRect,
+ local_rect: LayoutRect,
+ inner_rect: Option<LayoutRect>,
+ local_clip_rect: LayoutRect,
) -> SegmentBuilder {
let mut builder = SegmentBuilder {
items: Vec::new(),
bounding_rect: Some(local_rect),
inner_rect,
};
builder.push_clip_rect(local_rect, None, ClipMode::Clip);
@@ -201,59 +201,59 @@ impl SegmentBuilder {
// Push a region defined by an inner and outer rect where there
// is a mask required. This ensures that segments which intersect
// with these areas will get a clip mask task allocated. This
// is currently used to mark where a box-shadow region can affect
// the pixels of a clip-mask. It might be useful for other types
// such as dashed and dotted borders in the future.
pub fn push_mask_region(
&mut self,
- outer_rect: LayerRect,
- inner_rect: LayerRect,
+ outer_rect: LayoutRect,
+ inner_rect: LayoutRect,
inner_clip_mode: Option<ClipMode>,
) {
debug_assert!(outer_rect.contains_rect(&inner_rect));
let p0 = outer_rect.origin;
let p1 = inner_rect.origin;
let p2 = inner_rect.bottom_right();
let p3 = outer_rect.bottom_right();
let segments = &[
- LayerRect::new(
- LayerPoint::new(p0.x, p0.y),
- LayerSize::new(p1.x - p0.x, p1.y - p0.y),
+ LayoutRect::new(
+ LayoutPoint::new(p0.x, p0.y),
+ LayoutSize::new(p1.x - p0.x, p1.y - p0.y),
),
- LayerRect::new(
- LayerPoint::new(p2.x, p0.y),
- LayerSize::new(p3.x - p2.x, p1.y - p0.y),
+ LayoutRect::new(
+ LayoutPoint::new(p2.x, p0.y),
+ LayoutSize::new(p3.x - p2.x, p1.y - p0.y),
),
- LayerRect::new(
- LayerPoint::new(p2.x, p2.y),
- LayerSize::new(p3.x - p2.x, p3.y - p2.y),
+ LayoutRect::new(
+ LayoutPoint::new(p2.x, p2.y),
+ LayoutSize::new(p3.x - p2.x, p3.y - p2.y),
),
- LayerRect::new(
- LayerPoint::new(p0.x, p2.y),
- LayerSize::new(p1.x - p0.x, p3.y - p2.y),
+ LayoutRect::new(
+ LayoutPoint::new(p0.x, p2.y),
+ LayoutSize::new(p1.x - p0.x, p3.y - p2.y),
),
- LayerRect::new(
- LayerPoint::new(p1.x, p0.y),
- LayerSize::new(p2.x - p1.x, p1.y - p0.y),
+ LayoutRect::new(
+ LayoutPoint::new(p1.x, p0.y),
+ LayoutSize::new(p2.x - p1.x, p1.y - p0.y),
),
- LayerRect::new(
- LayerPoint::new(p2.x, p1.y),
- LayerSize::new(p3.x - p2.x, p2.y - p1.y),
+ LayoutRect::new(
+ LayoutPoint::new(p2.x, p1.y),
+ LayoutSize::new(p3.x - p2.x, p2.y - p1.y),
),
- LayerRect::new(
- LayerPoint::new(p1.x, p2.y),
- LayerSize::new(p2.x - p1.x, p3.y - p2.y),
+ LayoutRect::new(
+ LayoutPoint::new(p1.x, p2.y),
+ LayoutSize::new(p2.x - p1.x, p3.y - p2.y),
),
- LayerRect::new(
- LayerPoint::new(p0.x, p1.y),
- LayerSize::new(p1.x - p0.x, p2.y - p1.y),
+ LayoutRect::new(
+ LayoutPoint::new(p0.x, p1.y),
+ LayoutSize::new(p1.x - p0.x, p2.y - p1.y),
),
];
for segment in segments {
self.items.push(Item::new(
*segment,
None,
true
@@ -268,17 +268,17 @@ impl SegmentBuilder {
));
}
}
// Push some kind of clipping region into the segment builder.
// If radius is None, it's a simple rect.
pub fn push_clip_rect(
&mut self,
- rect: LayerRect,
+ rect: LayoutRect,
radius: Option<BorderRadius>,
mode: ClipMode,
) {
// Keep track of a minimal bounding rect for the set of
// segments that will be generated.
if mode == ClipMode::Clip {
self.bounding_rect = self.bounding_rect.and_then(|bounding_rect| {
bounding_rect.intersection(&rect)
@@ -293,62 +293,62 @@ impl SegmentBuilder {
match extract_inner_rect_safe(&rect, &radius) {
Some(inner) => {
let p0 = rect.origin;
let p1 = inner.origin;
let p2 = inner.bottom_right();
let p3 = rect.bottom_right();
let corner_segments = &[
- LayerRect::new(
- LayerPoint::new(p0.x, p0.y),
- LayerSize::new(p1.x - p0.x, p1.y - p0.y),
+ LayoutRect::new(
+ LayoutPoint::new(p0.x, p0.y),
+ LayoutSize::new(p1.x - p0.x, p1.y - p0.y),
),
- LayerRect::new(
- LayerPoint::new(p2.x, p0.y),
- LayerSize::new(p3.x - p2.x, p1.y - p0.y),
+ LayoutRect::new(
+ LayoutPoint::new(p2.x, p0.y),
+ LayoutSize::new(p3.x - p2.x, p1.y - p0.y),
),
- LayerRect::new(
- LayerPoint::new(p2.x, p2.y),
- LayerSize::new(p3.x - p2.x, p3.y - p2.y),
+ LayoutRect::new(
+ LayoutPoint::new(p2.x, p2.y),
+ LayoutSize::new(p3.x - p2.x, p3.y - p2.y),
),
- LayerRect::new(
- LayerPoint::new(p0.x, p2.y),
- LayerSize::new(p1.x - p0.x, p3.y - p2.y),
+ LayoutRect::new(
+ LayoutPoint::new(p0.x, p2.y),
+ LayoutSize::new(p1.x - p0.x, p3.y - p2.y),
),
];
for segment in corner_segments {
self.items.push(Item::new(
*segment,
mode,
true
));
}
let other_segments = &[
- LayerRect::new(
- LayerPoint::new(p1.x, p0.y),
- LayerSize::new(p2.x - p1.x, p1.y - p0.y),
+ LayoutRect::new(
+ LayoutPoint::new(p1.x, p0.y),
+ LayoutSize::new(p2.x - p1.x, p1.y - p0.y),
),
- LayerRect::new(
- LayerPoint::new(p2.x, p1.y),
- LayerSize::new(p3.x - p2.x, p2.y - p1.y),
+ LayoutRect::new(
+ LayoutPoint::new(p2.x, p1.y),
+ LayoutSize::new(p3.x - p2.x, p2.y - p1.y),
),
- LayerRect::new(
- LayerPoint::new(p1.x, p2.y),
- LayerSize::new(p2.x - p1.x, p3.y - p2.y),
+ LayoutRect::new(
+ LayoutPoint::new(p1.x, p2.y),
+ LayoutSize::new(p2.x - p1.x, p3.y - p2.y),
),
- LayerRect::new(
- LayerPoint::new(p0.x, p1.y),
- LayerSize::new(p1.x - p0.x, p2.y - p1.y),
+ LayoutRect::new(
+ LayoutPoint::new(p0.x, p1.y),
+ LayoutSize::new(p1.x - p0.x, p2.y - p1.y),
),
- LayerRect::new(
- LayerPoint::new(p1.x, p1.y),
- LayerSize::new(p2.x - p1.x, p2.y - p1.y),
+ LayoutRect::new(
+ LayoutPoint::new(p1.x, p1.y),
+ LayoutSize::new(p2.x - p1.x, p2.y - p1.y),
),
];
for segment in other_segments {
self.items.push(Item::new(
*segment,
mode,
false,
@@ -415,22 +415,22 @@ impl SegmentBuilder {
y_events.push(Event::region(inner_rect.origin.y));
y_events.push(Event::region(inner_rect.origin.y + inner_rect.size.height));
}
// Get the minimal bounding rect in app units. We will
// work in fixed point in order to avoid float precision
// error while handling events.
- let p0 = LayerPointAu::new(
+ let p0 = LayoutPointAu::new(
Au::from_f32_px(bounding_rect.origin.x),
Au::from_f32_px(bounding_rect.origin.y),
);
- let p1 = LayerPointAu::new(
+ let p1 = LayoutPointAu::new(
Au::from_f32_px(bounding_rect.origin.x + bounding_rect.size.width),
Au::from_f32_px(bounding_rect.origin.y + bounding_rect.size.height),
);
// Sort the events in ascending order.
x_events.sort();
y_events.sort();
@@ -553,47 +553,47 @@ fn emit_segment_if_needed(
has_clip_mask |= item.flags.contains(ItemFlags::HAS_MASK);
if item.mode == Some(ClipMode::ClipOut) && !item.flags.contains(ItemFlags::HAS_MASK) {
return None;
}
}
}
- let segment_rect = LayerRect::new(
- LayerPoint::new(
+ let segment_rect = LayoutRect::new(
+ LayoutPoint::new(
x0.to_f32_px(),
y0.to_f32_px(),
),
- LayerSize::new(
+ LayoutSize::new(
(x1 - x0).to_f32_px(),
(y1 - y0).to_f32_px(),
),
);
Some(Segment {
rect: segment_rect,
has_mask: has_clip_mask,
edge_flags: EdgeAaSegmentMask::empty(),
region_x,
region_y,
})
}
#[cfg(test)]
mod test {
- use api::{BorderRadius, ClipMode, LayerPoint, LayerRect, LayerSize};
+ use api::{BorderRadius, ClipMode, LayoutPoint, LayoutRect, LayoutSize};
use prim_store::EdgeAaSegmentMask;
use super::{Segment, SegmentBuilder};
use std::cmp;
- fn rect(x0: f32, y0: f32, x1: f32, y1: f32) -> LayerRect {
- LayerRect::new(
- LayerPoint::new(x0, y0),
- LayerSize::new(x1-x0, y1-y0),
+ fn rect(x0: f32, y0: f32, x1: f32, y1: f32) -> LayoutRect {
+ LayoutRect::new(
+ LayoutPoint::new(x0, y0),
+ LayoutSize::new(x1-x0, y1-y0),
)
}
fn seg(
x0: f32,
y0: f32,
x1: f32,
y1: f32,
@@ -609,19 +609,19 @@ mod test {
x1: f32,
y1: f32,
region_x: usize,
region_y: usize,
has_mask: bool,
edge_flags: Option<EdgeAaSegmentMask>,
) -> Segment {
Segment {
- rect: LayerRect::new(
- LayerPoint::new(x0, y0),
- LayerSize::new(x1-x0, y1-y0),
+ rect: LayoutRect::new(
+ LayoutPoint::new(x0, y0),
+ LayoutSize::new(x1-x0, y1-y0),
),
has_mask,
edge_flags: edge_flags.unwrap_or(EdgeAaSegmentMask::empty()),
region_x,
region_y,
}
}
@@ -632,20 +632,20 @@ mod test {
(
(r0.origin.x, r0.origin.y, r0.size.width, r0.size.height)
).partial_cmp(&
(r1.origin.x, r1.origin.y, r1.size.width, r1.size.height)
).unwrap()
}
fn seg_test(
- local_rect: LayerRect,
- inner_rect: Option<LayerRect>,
- local_clip_rect: LayerRect,
- clips: &[(LayerRect, Option<BorderRadius>, ClipMode)],
+ local_rect: LayoutRect,
+ inner_rect: Option<LayoutRect>,
+ local_clip_rect: LayoutRect,
+ clips: &[(LayoutRect, Option<BorderRadius>, ClipMode)],
expected_segments: &mut [Segment]
) {
let mut sb = SegmentBuilder::new(
local_rect,
inner_rect,
local_clip_rect,
);
let mut segments = Vec::new();
--- a/gfx/webrender/src/shade.rs
+++ b/gfx/webrender/src/shade.rs
@@ -48,16 +48,17 @@ pub const IMAGE_BUFFER_KINDS: [ImageBuff
ImageBufferKind::TextureRect,
ImageBufferKind::TextureExternal,
ImageBufferKind::Texture2DArray,
];
const TRANSFORM_FEATURE: &str = "TRANSFORM";
const ALPHA_FEATURE: &str = "ALPHA_PASS";
const DITHERING_FEATURE: &str = "DITHERING";
+const DUAL_SOURCE_FEATURE: &str = "DUAL_SOURCE_BLENDING";
pub(crate) enum ShaderKind {
Primitive,
Cache(VertexArrayKind),
ClipCache,
Brush,
Text,
#[allow(dead_code)]
@@ -176,24 +177,26 @@ impl LazilyCompiledShader {
// alpha:
// Used for brush primitives in the alpha
// pass. Assumes that AA should be applied
// along the primitive edge, and also that
// clip mask is present.
struct BrushShader {
opaque: LazilyCompiledShader,
alpha: LazilyCompiledShader,
+ dual_source: Option<LazilyCompiledShader>,
}
impl BrushShader {
fn new(
name: &'static str,
device: &mut Device,
features: &[&'static str],
precache: bool,
+ dual_source: bool,
) -> Result<Self, ShaderError> {
let opaque = LazilyCompiledShader::new(
ShaderKind::Brush,
name,
features,
device,
precache,
)?;
@@ -204,34 +207,62 @@ impl BrushShader {
let alpha = LazilyCompiledShader::new(
ShaderKind::Brush,
name,
&alpha_features,
device,
precache,
)?;
- Ok(BrushShader { opaque, alpha })
+ let dual_source = if dual_source {
+ let mut dual_source_features = alpha_features.to_vec();
+ dual_source_features.push(DUAL_SOURCE_FEATURE);
+
+ let shader = LazilyCompiledShader::new(
+ ShaderKind::Brush,
+ name,
+ &dual_source_features,
+ device,
+ precache,
+ )?;
+
+ Some(shader)
+ } else {
+ None
+ };
+
+ Ok(BrushShader {
+ opaque,
+ alpha,
+ dual_source,
+ })
}
fn get(&mut self, blend_mode: BlendMode) -> &mut LazilyCompiledShader {
match blend_mode {
BlendMode::None => &mut self.opaque,
BlendMode::Alpha |
BlendMode::PremultipliedAlpha |
BlendMode::PremultipliedDestOut |
- BlendMode::SubpixelDualSource |
BlendMode::SubpixelConstantTextColor(..) |
BlendMode::SubpixelWithBgColor => &mut self.alpha,
+ BlendMode::SubpixelDualSource => {
+ self.dual_source
+ .as_mut()
+ .expect("bug: no dual source shader loaded")
+ }
}
}
fn deinit(self, device: &mut Device) {
self.opaque.deinit(device);
self.alpha.deinit(device);
+ if let Some(dual_source) = self.dual_source {
+ dual_source.deinit(device);
+ }
}
}
struct PrimitiveShader {
simple: LazilyCompiledShader,
transform: LazilyCompiledShader,
}
@@ -364,16 +395,17 @@ fn create_prim_shader(
}
debug!("PrimShader {}", name);
let vertex_descriptor = match vertex_format {
VertexArrayKind::Primitive => desc::PRIM_INSTANCES,
VertexArrayKind::Blur => desc::BLUR,
VertexArrayKind::Clip => desc::CLIP,
+ VertexArrayKind::DashAndDot => desc::BORDER_CORNER_DASH_AND_DOT,
VertexArrayKind::VectorStencil => desc::VECTOR_STENCIL,
VertexArrayKind::VectorCover => desc::VECTOR_COVER,
};
let program = device.create_program(name, &prefix, &vertex_descriptor);
if let Ok(ref program) = program {
device.bind_shader_samplers(
@@ -482,52 +514,57 @@ impl Shaders {
None
};
let brush_solid = BrushShader::new(
"brush_solid",
device,
&[],
options.precache_shaders,
+ false,
)?;
let brush_blend = BrushShader::new(
"brush_blend",
device,
&[],
options.precache_shaders,
+ false,
)?;
let brush_mix_blend = BrushShader::new(
"brush_mix_blend",
device,
&[],
options.precache_shaders,
+ false,
)?;
let brush_radial_gradient = BrushShader::new(
"brush_radial_gradient",
device,
if options.enable_dithering {
&[DITHERING_FEATURE]
} else {
&[]
},
options.precache_shaders,
+ false,
)?;
let brush_linear_gradient = BrushShader::new(
"brush_linear_gradient",
device,
if options.enable_dithering {
&[DITHERING_FEATURE]
} else {
&[]
},
options.precache_shaders,
+ false,
)?;
let cs_blur_a8 = LazilyCompiledShader::new(
ShaderKind::Cache(VertexArrayKind::Blur),
"cs_blur",
&["ALPHA_TARGET"],
device,
options.precache_shaders,
@@ -614,16 +651,17 @@ impl Shaders {
&image_features,
options.precache_shaders,
)?);
brush_image[buffer_kind] = Some(BrushShader::new(
"brush_image",
device,
&image_features,
options.precache_shaders,
+ true,
)?);
}
image_features.clear();
}
// All yuv_image configuration.
let mut yuv_features = Vec::new();
let yuv_shader_num = IMAGE_BUFFER_KINDS.len() * YUV_FORMATS.len() * YUV_COLOR_SPACES.len();
@@ -649,16 +687,17 @@ impl Shaders {
yuv_features.push(feature_string);
}
let shader = BrushShader::new(
"brush_yuv_image",
device,
&yuv_features,
options.precache_shaders,
+ false,
)?;
let index = Self::get_yuv_shader_index(
*image_buffer_kind,
*format_kind,
*color_space_kind,
);
brush_yuv_image[index] = Some(shader);
yuv_features.clear();
@@ -760,18 +799,26 @@ impl Shaders {
.as_mut()
.expect("Unsupported YUV shader kind")
}
};
brush_shader.get(key.blend_mode)
}
BatchKind::Transformable(transform_kind, batch_kind) => {
let prim_shader = match batch_kind {
- TransformBatchKind::TextRun(..) => {
- unreachable!("bug: text batches are special cased");
+ TransformBatchKind::TextRun(glyph_format) => {
+ let text_shader = match key.blend_mode {
+ BlendMode::SubpixelDualSource => {
+ &mut self.ps_text_run_dual_source
+ }
+ _ => {
+ &mut self.ps_text_run
+ }
+ };
+ return text_shader.get(glyph_format, transform_kind);
}
TransformBatchKind::Image(image_buffer_kind) => {
self.ps_image[image_buffer_kind as usize]
.as_mut()
.expect("Unsupported image shader kind")
}
TransformBatchKind::BorderCorner => {
&mut self.ps_border_corner
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -230,17 +230,17 @@ pub struct TextureCache {
// A list of texture IDs that represent native
// texture handles. This indirection allows the texture
// cache to create / destroy / reuse texture handles
// without knowing anything about the device code.
cache_textures: CacheTextureIdList,
// A list of updates that need to be applied to the
// texture cache in the rendering thread this frame.
- #[cfg_attr(feature = "serde", serde(skip))]
+ #[cfg_attr(all(feature = "serde", any(feature = "capture", feature = "replay")), serde(skip))]
pending_updates: TextureUpdateList,
// The current frame ID. Used for cache eviction policies.
frame_id: FrameId,
// Maintains the list of all current items in
// the texture cache.
entries: FreeList<CacheEntry, CacheEntryMarker>,
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -1,14 +1,14 @@
/* 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 api::{ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint};
-use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, FilterOp, ImageFormat, LayerRect};
+use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, FilterOp, ImageFormat, LayoutRect};
use api::{MixBlendMode, PipelineId};
use batch::{AlphaBatchBuilder, AlphaBatchContainer, ClipBatcher, resolve_image};
use clip::{ClipStore};
use clip_scroll_tree::{ClipScrollTree, ClipScrollNodeIndex};
use device::{FrameId, Texture};
#[cfg(feature = "pathfinder")]
use euclid::{TypedPoint2D, TypedVector2D};
use gpu_cache::{GpuCache};
@@ -29,17 +29,17 @@ use texture_allocator::GuillotineAllocat
use webrender_api::{DevicePixel, FontRenderMode};
const MIN_TARGET_SIZE: u32 = 2048;
#[derive(Debug)]
pub struct ScrollbarPrimitive {
pub scroll_frame_index: ClipScrollNodeIndex,
pub prim_index: PrimitiveIndex,
- pub frame_rect: LayerRect,
+ pub frame_rect: LayoutRect,
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct RenderTargetIndex(pub usize);
pub struct RenderTargetContext<'a, 'rc> {
@@ -933,17 +933,17 @@ pub struct Frame {
pub background_color: Option<ColorF>,
pub layer: DocumentLayer,
pub device_pixel_ratio: f32,
pub passes: Vec<RenderPass>,
#[cfg_attr(any(feature = "capture", feature = "replay"), serde(default = "FrameProfileCounters::new", skip))]
pub profile_counters: FrameProfileCounters,
pub node_data: Vec<ClipScrollNodeData>,
- pub clip_chain_local_clip_rects: Vec<LayerRect>,
+ pub clip_chain_local_clip_rects: Vec<LayoutRect>,
pub render_tasks: RenderTaskTree,
/// The GPU cache frame that the contents of Self depend on
pub gpu_cache_frame_id: FrameId,
/// List of textures that we don't know about yet
/// from the backend thread. The render thread
/// will use a callback to resolve these and
--- a/gfx/webrender/src/util.rs
+++ b/gfx/webrender/src/util.rs
@@ -1,15 +1,15 @@
/* 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 api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
-use api::{DevicePoint, DeviceRect, DeviceSize, LayerPixel, LayerPoint, LayerRect, LayerSize};
-use api::{LayoutPixel, WorldPixel, WorldRect};
+use api::{DevicePoint, DeviceRect, DeviceSize, LayoutPixel, LayoutPoint, LayoutRect, LayoutSize};
+use api::{WorldPixel, WorldRect};
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedPoint3D, TypedRect, TypedSize2D};
use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D};
use num_traits::Zero;
use std::{i32, f32};
// Matches the definition of SK_ScalarNearlyZero in Skia.
const NEARLY_ZERO: f32 = 1.0 / 4096.0;
@@ -152,18 +152,18 @@ pub fn rect_from_points_f(x0: f32, y0: f
Rect::new(Point2D::new(x0, y0), Size2D::new(x1 - x0, y1 - y0))
}
pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
(b - a) * t + a
}
pub fn calculate_screen_bounding_rect(
- transform: &LayerToWorldFastTransform,
- rect: &LayerRect,
+ transform: &LayoutToWorldFastTransform,
+ rect: &LayoutRect,
device_pixel_scale: DevicePixelScale,
) -> DeviceIntRect {
let points = [
transform.transform_point2d(&rect.origin),
transform.transform_point2d(&rect.top_right()),
transform.transform_point2d(&rect.bottom_left()),
transform.transform_point2d(&rect.bottom_right()),
];
@@ -304,21 +304,21 @@ pub mod test {
assert_eq!(m1.inverse_project(&p0), Some(Point2D::new(2.0, 2.0)));
}
}
pub trait MaxRect {
fn max_rect() -> Self;
}
-impl MaxRect for LayerRect {
+impl MaxRect for LayoutRect {
fn max_rect() -> Self {
- LayerRect::new(
- LayerPoint::new(f32::MIN / 2.0, f32::MIN / 2.0),
- LayerSize::new(f32::MAX, f32::MAX),
+ LayoutRect::new(
+ LayoutPoint::new(f32::MIN / 2.0, f32::MIN / 2.0),
+ LayoutSize::new(f32::MAX, f32::MAX),
)
}
}
impl MaxRect for DeviceIntRect {
fn max_rect() -> Self {
DeviceIntRect::new(
DeviceIntPoint::new(i32::MIN / 2, i32::MIN / 2),
@@ -551,11 +551,10 @@ impl<Src, Dst> Into<TypedTransform3D<f32
impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
fn from(vector: TypedVector2D<f32, Src>) -> FastTransform<Src, Dst> {
FastTransform::with_vector(vector)
}
}
pub type LayoutFastTransform = FastTransform<LayoutPixel, LayoutPixel>;
-pub type LayerFastTransform = FastTransform<LayerPixel, LayerPixel>;
-pub type LayerToWorldFastTransform = FastTransform<LayerPixel, WorldPixel>;
-pub type WorldToLayerFastTransform = FastTransform<WorldPixel, LayerPixel>;
+pub type LayoutToWorldFastTransform = FastTransform<LayoutPixel, WorldPixel>;
+pub type WorldToLayoutFastTransform = FastTransform<WorldPixel, LayoutPixel>;
\ No newline at end of file
--- a/gfx/webrender_api/src/api.rs
+++ b/gfx/webrender_api/src/api.rs
@@ -214,35 +214,31 @@ impl Transaction {
/// is reset back to `None`.
pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id));
}
/// Supplies a new frame to WebRender.
///
/// Non-blocking, it notifies a worker process which processes the display list.
- /// When it's done and a RenderNotifier has been set in `webrender::Renderer`,
- /// [new_frame_ready()][notifier] gets called.
///
/// Note: Scrolling doesn't require an own Frame.
///
/// Arguments:
///
/// * `document_id`: Target Document ID.
/// * `epoch`: The unique Frame ID, monotonically increasing.
/// * `background`: The background color of this pipeline.
/// * `viewport_size`: The size of the viewport for this frame.
/// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
/// * `content_size`: The total screen space size of this display list's display items.
/// * `display_list`: The root Display list used in this frame.
/// * `preserve_frame_state`: If a previous frame exists which matches this pipeline
/// id, this setting determines if frame state (such as scrolling
/// position) should be preserved for this new display list.
- ///
- /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
pub fn set_display_list(
&mut self,
epoch: Epoch,
background: Option<ColorF>,
viewport_size: LayoutSize,
(pipeline_id, content_size, display_list): (PipelineId, LayoutSize, BuiltDisplayList),
preserve_frame_state: bool,
) {
@@ -308,17 +304,23 @@ impl Transaction {
pub fn set_pinch_zoom(&mut self, pinch_zoom: ZoomFactor) {
self.scene_ops.push(SceneMsg::SetPinchZoom(pinch_zoom));
}
pub fn set_pan(&mut self, pan: DeviceIntPoint) {
self.frame_ops.push(FrameMsg::SetPan(pan));
}
- /// Generate a new frame.
+ /// Generate a new frame. When it's done and a RenderNotifier has been set
+ /// in `webrender::Renderer`, [new_frame_ready()][notifier] gets called.
+ /// Note that the notifier is called even if the frame generation was a
+ /// no-op; the arguments passed to `new_frame_ready` will provide information
+ /// as to what happened.
+ ///
+ /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
pub fn generate_frame(&mut self) {
self.generate_frame = true;
}
/// Supply a list of animated property bindings that should be used to resolve
/// bindings in the current display list.
pub fn update_dynamic_properties(&mut self, properties: DynamicProperties) {
self.frame_ops.push(FrameMsg::UpdateDynamicProperties(properties));
@@ -1102,14 +1104,14 @@ pub struct PropertyValue<T> {
pub struct DynamicProperties {
pub transforms: Vec<PropertyValue<LayoutTransform>>,
pub floats: Vec<PropertyValue<f32>>,
}
pub trait RenderNotifier: Send {
fn clone(&self) -> Box<RenderNotifier>;
fn wake_up(&self);
- fn new_document_ready(&self, DocumentId, scrolled: bool, composite_needed: bool);
+ fn new_frame_ready(&self, DocumentId, scrolled: bool, composite_needed: bool);
fn external_event(&self, _evt: ExternalEvent) {
unimplemented!()
}
fn shut_down(&self) {}
}
--- a/gfx/webrender_api/src/color.rs
+++ b/gfx/webrender_api/src/color.rs
@@ -58,16 +58,26 @@ impl ColorF {
ColorF {
r: self.r * scale,
g: self.g * scale,
b: self.b * scale,
a: self.a,
}
}
+ // Scale the alpha by a given factor.
+ pub fn scale_alpha(&self, scale: f32) -> Self {
+ ColorF {
+ r: self.r,
+ g: self.g,
+ b: self.b,
+ a: self.a * scale,
+ }
+ }
+
pub fn to_array(&self) -> [f32; 4] {
[self.r, self.g, self.b, self.a]
}
/// Multiply the RGB components with the alpha channel.
pub fn premultiplied(&self) -> PremultipliedColorF {
let c = self.scale_rgb(self.a);
PremultipliedColorF { r: c.r, g: c.g, b: c.b, a: c.a }
--- a/gfx/webrender_api/src/display_item.rs
+++ b/gfx/webrender_api/src/display_item.rs
@@ -1,17 +1,17 @@
/* 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/. */
#[cfg(any(feature = "serialize", feature = "deserialize"))]
use GlyphInstance;
use euclid::{SideOffsets2D, TypedRect};
use std::ops::Not;
-use {ColorF, FontInstanceKey, GlyphOptions, ImageKey, LayerPixel, LayoutPixel, LayoutPoint};
+use {ColorF, FontInstanceKey, GlyphOptions, ImageKey, LayoutPixel, LayoutPoint};
use {LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, PipelineId, PropertyBinding};
// NOTE: some of these structs have an "IMPLICIT" comment.
// This indicates that the BuiltDisplayList will have serialized
// a list of values nearby that this item consumes. The traversal
// iterator should handle finding these.
@@ -64,36 +64,35 @@ pub type DisplayItem = GenericDisplayIte
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct PrimitiveInfo<T> {
pub rect: TypedRect<f32, T>,
pub clip_rect: TypedRect<f32, T>,
pub is_backface_visible: bool,
pub tag: Option<ItemTag>,
}
-impl LayerPrimitiveInfo {
- pub fn new(rect: TypedRect<f32, LayerPixel>) -> Self {
+impl LayoutPrimitiveInfo {
+ pub fn new(rect: TypedRect<f32, LayoutPixel>) -> Self {
Self::with_clip_rect(rect, rect)
}
pub fn with_clip_rect(
- rect: TypedRect<f32, LayerPixel>,
- clip_rect: TypedRect<f32, LayerPixel>,
+ rect: TypedRect<f32, LayoutPixel>,
+ clip_rect: TypedRect<f32, LayoutPixel>,
) -> Self {
PrimitiveInfo {
rect,
clip_rect,
is_backface_visible: true,
tag: None,
}
}
}
pub type LayoutPrimitiveInfo = PrimitiveInfo<LayoutPixel>;
-pub type LayerPrimitiveInfo = PrimitiveInfo<LayerPixel>;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum SpecificDisplayItem {
Clip(ClipDisplayItem),
ScrollFrame(ScrollFrameDisplayItem),
StickyFrame(StickyFrameDisplayItem),
Rectangle(RectangleDisplayItem),
@@ -663,22 +662,22 @@ impl LocalClip {
),
}
}
pub fn clip_by(&self, rect: &LayoutRect) -> LocalClip {
match *self {
LocalClip::Rect(clip_rect) => {
LocalClip::Rect(
- clip_rect.intersection(rect).unwrap_or(LayoutRect::zero())
+ clip_rect.intersection(rect).unwrap_or_else(LayoutRect::zero)
)
}
LocalClip::RoundedRect(clip_rect, complex) => {
LocalClip::RoundedRect(
- clip_rect.intersection(rect).unwrap_or(LayoutRect::zero()),
+ clip_rect.intersection(rect).unwrap_or_else(LayoutRect::zero),
complex,
)
}
}
}
}
#[repr(C)]
--- a/gfx/webrender_api/src/display_list.rs
+++ b/gfx/webrender_api/src/display_list.rs
@@ -12,17 +12,17 @@ use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
use std::marker::PhantomData;
use std::{io, mem, ptr, slice};
use time::precise_time_ns;
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BorderWidths, BoxShadowClipMode};
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
use {FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, Gradient, GradientDisplayItem, GradientStop};
-use {IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering, LayerPrimitiveInfo};
+use {IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering};
use {LayoutPoint, LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
use {LineDisplayItem, LineOrientation, LineStyle, MixBlendMode, PipelineId, PropertyBinding};
use {PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
use {RectangleDisplayItem, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity, Shadow};
use {SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, StickyOffsetBounds};
use {TextDisplayItem, TransformStyle, YuvColorSpace, YuvData, YuvImageDisplayItem};
// We don't want to push a long text-run. If a text-run is too long, split it into several parts.
@@ -326,19 +326,19 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
pub fn display_item(&self) -> &DisplayItem {
&self.iter.cur_item
}
pub fn rect(&self) -> LayoutRect {
self.iter.cur_item.info.rect
}
- pub fn get_layer_primitive_info(&self, offset: &LayoutVector2D) -> LayerPrimitiveInfo {
+ pub fn get_layout_primitive_info(&self, offset: &LayoutVector2D) -> LayoutPrimitiveInfo {
let info = self.iter.cur_item.info;
- LayerPrimitiveInfo {
+ LayoutPrimitiveInfo {
rect: info.rect.translate(offset),
clip_rect: info.clip_rect.translate(offset),
is_backface_visible: info.is_backface_visible,
tag: info.tag,
}
}
pub fn clip_rect(&self) -> &LayoutRect {
--- a/gfx/webrender_api/src/image.rs
+++ b/gfx/webrender_api/src/image.rs
@@ -118,17 +118,17 @@ pub enum ImageData {
}
mod serde_image_data_raw {
extern crate serde_bytes;
use std::sync::Arc;
use serde::{Deserializer, Serializer};
- pub fn serialize<'a, S: Serializer>(bytes: &'a Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
+ pub fn serialize<S: Serializer>(bytes: &Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
serde_bytes::serialize(bytes.as_slice(), serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<Vec<u8>>, D::Error> {
serde_bytes::deserialize(deserializer).map(Arc::new)
}
}
--- a/gfx/webrender_api/src/lib.rs
+++ b/gfx/webrender_api/src/lib.rs
@@ -1,14 +1,14 @@
/* 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/. */
#![cfg_attr(feature = "nightly", feature(nonzero))]
-#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, float_cmp))]
+#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, too_many_arguments, unreadable_literal))]
extern crate app_units;
extern crate bincode;
#[macro_use]
extern crate bitflags;
extern crate byteorder;
#[cfg(feature = "nightly")]
extern crate core;
--- a/gfx/webrender_api/src/units.rs
+++ b/gfx/webrender_api/src/units.rs
@@ -40,36 +40,25 @@ pub type DeviceSize = TypedSize2D<f32, D
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct PicturePixel;
pub type PictureIntRect = TypedRect<i32, PicturePixel>;
pub type PictureIntPoint = TypedPoint2D<i32, PicturePixel>;
pub type PictureIntSize = TypedSize2D<i32, PicturePixel>;
/// Geometry in a stacking context's local coordinate space (logical pixels).
-///
-/// For now layout pixels are equivalent to layer pixels, but it may change.
-pub type LayoutPixel = LayerPixel;
-
-pub type LayoutRect = LayerRect;
-pub type LayoutPoint = LayerPoint;
-pub type LayoutVector2D = LayerVector2D;
-pub type LayoutVector3D = LayerVector3D;
-pub type LayoutSize = LayerSize;
+#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
+pub struct LayoutPixel;
-/// Geometry in a layer's local coordinate space (logical pixels).
-#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
-pub struct LayerPixel;
-
-pub type LayerRect = TypedRect<f32, LayerPixel>;
-pub type LayerPoint = TypedPoint2D<f32, LayerPixel>;
-pub type LayerPoint3D = TypedPoint3D<f32, LayerPixel>;
-pub type LayerVector2D = TypedVector2D<f32, LayerPixel>;
-pub type LayerVector3D = TypedVector3D<f32, LayerPixel>;
-pub type LayerSize = TypedSize2D<f32, LayerPixel>;
+pub type LayoutRect = TypedRect<f32, LayoutPixel>;
+pub type LayoutPoint = TypedPoint2D<f32, LayoutPixel>;
+pub type LayoutPoint3D = TypedPoint3D<f32, LayoutPixel>;
+pub type LayoutVector2D = TypedVector2D<f32, LayoutPixel>;
+pub type LayoutVector3D = TypedVector3D<f32, LayoutPixel>;
+pub type LayoutSize = TypedSize2D<f32, LayoutPixel>;
/// Geometry in a layer's scrollable parent coordinate space (logical pixels).
///
/// Some layers are scrollable while some are not. There is a distinction between
/// a layer's parent layer and a layer's scrollable parent layer (its closest parent
/// that is scrollable, but not necessarily its immediate parent). Most of the internal
/// transforms are expressed in terms of the scrollable parent and not the immediate
/// parent.
@@ -94,38 +83,37 @@ pub type WorldVector3D = TypedVector3D<f
/// Offset in number of tiles.
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Tiles;
pub type TileOffset = TypedPoint2D<u16, Tiles>;
/// Scaling ratio from world pixels to device pixels.
pub type DevicePixelScale = TypedScale<f32, WorldPixel, DevicePixel>;
-/// Scaling ratio from layer to world. Used for cases where we know the layer
+/// Scaling ratio from layout to world. Used for cases where we know the layout
/// is in world space, or specifically want to treat it this way.
-pub type LayerToWorldScale = TypedScale<f32, LayerPixel, WorldPixel>;
+pub type LayoutToWorldScale = TypedScale<f32, LayoutPixel, WorldPixel>;
pub type LayoutTransform = TypedTransform3D<f32, LayoutPixel, LayoutPixel>;
-pub type LayerTransform = TypedTransform3D<f32, LayerPixel, LayerPixel>;
-pub type LayerToScrollTransform = TypedTransform3D<f32, LayerPixel, ScrollLayerPixel>;
-pub type ScrollToLayerTransform = TypedTransform3D<f32, ScrollLayerPixel, LayerPixel>;
-pub type LayerToWorldTransform = TypedTransform3D<f32, LayerPixel, WorldPixel>;
-pub type WorldToLayerTransform = TypedTransform3D<f32, WorldPixel, LayerPixel>;
+pub type LayoutToScrollTransform = TypedTransform3D<f32, LayoutPixel, ScrollLayerPixel>;
+pub type ScrollToLayoutTransform = TypedTransform3D<f32, ScrollLayerPixel, LayoutPixel>;
+pub type LayoutToWorldTransform = TypedTransform3D<f32, LayoutPixel, WorldPixel>;
+pub type WorldToLayoutTransform = TypedTransform3D<f32, WorldPixel, LayoutPixel>;
pub type ScrollToWorldTransform = TypedTransform3D<f32, ScrollLayerPixel, WorldPixel>;
// Fixed position coordinates, to avoid float precision errors.
-pub type LayerPointAu = TypedPoint2D<Au, LayerPixel>;
-pub type LayerRectAu = TypedRect<Au, LayerPixel>;
-pub type LayerSizeAu = TypedSize2D<Au, LayerPixel>;
+pub type LayoutPointAu = TypedPoint2D<Au, LayoutPixel>;
+pub type LayoutRectAu = TypedRect<Au, LayoutPixel>;
+pub type LayoutSizeAu = TypedSize2D<Au, LayoutPixel>;
-pub fn as_scroll_parent_rect(rect: &LayerRect) -> ScrollLayerRect {
+pub fn as_scroll_parent_rect(rect: &LayoutRect) -> ScrollLayerRect {
ScrollLayerRect::from_untyped(&rect.to_untyped())
}
-pub fn as_scroll_parent_vector(vector: &LayerVector2D) -> ScrollLayerVector2D {
+pub fn as_scroll_parent_vector(vector: &LayoutVector2D) -> ScrollLayerVector2D {
ScrollLayerVector2D::from_untyped(&vector.to_untyped())
}
/// Stores two coordinates in texel space. The coordinates
/// are stored in texel coordinates because the texture atlas
/// may grow. Storing them as texel coords and normalizing
/// the UVs in the vertex shader means nothing needs to be
/// updated on the CPU when the texture size changes.
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-ad06d8e05e8475c9788cffa7e6cbac70acbdb399
+751236199b39bb8dac78522713133ca18c603fb3
--- a/gfx/wrench/src/main.rs
+++ b/gfx/wrench/src/main.rs
@@ -344,17 +344,17 @@ impl RenderNotifier for Notifier {
fn wake_up(&self) {
self.tx.send(NotifierEvent::WakeUp).unwrap();
}
fn shut_down(&self) {
self.tx.send(NotifierEvent::ShutDown).unwrap();
}
- fn new_document_ready(&self, _: DocumentId, _scrolled: bool, composite_needed: bool) {
+ fn new_frame_ready(&self, _: DocumentId, _scrolled: bool, composite_needed: bool) {
if composite_needed {
self.wake_up();
}
}
}
fn create_notifier() -> (Box<RenderNotifier>, Receiver<NotifierEvent>) {
let (tx, rx) = channel();
--- a/gfx/wrench/src/reftest.rs
+++ b/gfx/wrench/src/reftest.rs
@@ -486,17 +486,21 @@ impl<'a> ReftestHarness<'a> {
reader.allow_mipmaps(allow_mipmaps);
reader.do_frame(self.wrench);
// wait for the frame
self.rx.recv().unwrap();
let stats = self.wrench.render();
let window_size = self.window.get_inner_size();
- assert!(size.width <= window_size.width && size.height <= window_size.height);
+ assert!(
+ size.width <= window_size.width &&
+ size.height <= window_size.height,
+ format!("size={:?} ws={:?}", size, window_size)
+ );
// taking the bottom left sub-rectangle
let rect = DeviceUintRect::new(DeviceUintPoint::new(0, window_size.height - size.height), size);
let pixels = self.wrench.renderer.read_pixels_rgba8(rect);
self.window.swap_buffers();
let write_debug_images = false;
if write_debug_images {
--- a/gfx/wrench/src/scene.rs
+++ b/gfx/wrench/src/scene.rs
@@ -1,15 +1,15 @@
/* 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 std::collections::HashMap;
use webrender::api::{BuiltDisplayList, ColorF, Epoch};
-use webrender::api::{LayerSize, PipelineId};
+use webrender::api::{LayoutSize, PipelineId};
use webrender::api::{PropertyBinding, PropertyBindingId, LayoutTransform, DynamicProperties};
/// Stores a map of the animated property bindings for the current display list. These
/// can be used to animate the transform and/or opacity of a display list without
/// re-submitting the display list itself.
#[derive(Default)]
pub struct SceneProperties {
transform_properties: HashMap<PropertyBindingId, LayoutTransform>,
@@ -69,17 +69,17 @@ impl SceneProperties {
}
}
}
/// A representation of the layout within the display port for a given document or iframe.
#[derive(Debug)]
pub struct ScenePipeline {
pub epoch: Epoch,
- pub viewport_size: LayerSize,
+ pub viewport_size: LayoutSize,
pub background_color: Option<ColorF>,
}
/// A complete representation of the layout bundling visible pipelines together.
pub struct Scene {
pub properties: SceneProperties,
pub root_pipeline_id: Option<PipelineId>,
pub pipeline_map: HashMap<PipelineId, ScenePipeline>,
@@ -108,17 +108,17 @@ impl Scene {
self.display_lists.remove(pipeline_id);
}
pub fn begin_display_list(
&mut self,
pipeline_id: &PipelineId,
epoch: &Epoch,
background_color: &Option<ColorF>,
- viewport_size: &LayerSize,
+ viewport_size: &LayoutSize,
) {
let new_pipeline = ScenePipeline {
epoch: epoch.clone(),
viewport_size: viewport_size.clone(),
background_color: background_color.clone(),
};
self.pipeline_map.insert(pipeline_id.clone(), new_pipeline);
--- a/gfx/wrench/src/wrench.rs
+++ b/gfx/wrench/src/wrench.rs
@@ -104,17 +104,17 @@ impl RenderNotifier for Notifier {
fn clone(&self) -> Box<RenderNotifier> {
Box::new(Notifier(self.0.clone()))
}
fn wake_up(&self) {
self.update(false);
}
- fn new_document_ready(&self, _: DocumentId, scrolled: bool, _composite_needed: bool) {
+ fn new_frame_ready(&self, _: DocumentId, scrolled: bool, _composite_needed: bool) {
self.update(!scrolled);
}
}
pub trait WrenchThing {
fn next_frame(&mut self);
fn prev_frame(&mut self);
fn do_frame(&mut self, &mut Wrench) -> u32;
@@ -278,53 +278,53 @@ impl Wrench {
pub fn layout_simple_ascii(
&mut self,
font_key: FontKey,
instance_key: FontInstanceKey,
render_mode: Option<FontRenderMode>,
text: &str,
size: Au,
- origin: LayerPoint,
+ origin: LayoutPoint,
flags: FontInstanceFlags,
- ) -> (Vec<u32>, Vec<LayerPoint>, LayoutRect) {
+ ) -> (Vec<u32>, Vec<LayoutPoint>, LayoutRect) {
// Map the string codepoints to glyph indices in this font.
// Just drop any glyph that isn't present in this font.
let indices: Vec<u32> = self.api
.get_glyph_indices(font_key, text)
.iter()
.filter_map(|idx| *idx)
.collect();
let render_mode = render_mode.unwrap_or(<FontInstanceOptions as Default>::default().render_mode);
let subpx_dir = SubpixelDirection::Horizontal.limit_by(render_mode);
// Retrieve the metrics for each glyph.
let mut keys = Vec::new();
for glyph_index in &indices {
keys.push(GlyphKey::new(
*glyph_index,
- LayerPoint::zero(),
+ LayoutPoint::zero(),
render_mode,
subpx_dir,
));
}
let metrics = self.api.get_glyph_dimensions(instance_key, keys);
let mut bounding_rect = LayoutRect::zero();
let mut positions = Vec::new();
let mut cursor = origin;
let direction = if flags.contains(FontInstanceFlags::TRANSPOSE) {
- LayerVector2D::new(
+ LayoutVector2D::new(
0.0,
if flags.contains(FontInstanceFlags::FLIP_Y) { -1.0 } else { 1.0 },
)
} else {
- LayerVector2D::new(
+ LayoutVector2D::new(
if flags.contains(FontInstanceFlags::FLIP_X) { -1.0 } else { 1.0 },
0.0,
)
};
for metric in metrics {
positions.push(cursor);
match metric {
@@ -495,18 +495,18 @@ impl Wrench {
pub fn begin_frame(&mut self) {
self.frame_start_sender.push(time::SteadyTime::now());
}
pub fn send_lists(
&mut self,
frame_number: u32,
- display_lists: Vec<(PipelineId, LayerSize, BuiltDisplayList)>,
- scroll_offsets: &HashMap<ExternalScrollId, LayerPoint>,
+ display_lists: Vec<(PipelineId, LayoutSize, BuiltDisplayList)>,
+ scroll_offsets: &HashMap<ExternalScrollId, LayoutPoint>,
) {
let root_background_color = Some(ColorF::new(1.0, 1.0, 1.0, 1.0));
let mut txn = Transaction::new();
for display_list in display_lists {
txn.set_display_list(
Epoch(frame_number),
root_background_color,
--- a/gfx/wrench/src/yaml_frame_reader.rs
+++ b/gfx/wrench/src/yaml_frame_reader.rs
@@ -188,17 +188,17 @@ pub struct YamlFrameReader {
include_only: Vec<String>,
watch_source: bool,
list_resources: bool,
/// A HashMap of offsets which specify what scroll offsets particular
/// scroll layers should be initialized with.
- scroll_offsets: HashMap<ExternalScrollId, LayerPoint>,
+ scroll_offsets: HashMap<ExternalScrollId, LayoutPoint>,
image_map: HashMap<(PathBuf, Option<i64>), (ImageKey, LayoutSize)>,
fonts: HashMap<FontDescriptor, FontKey>,
font_instances: HashMap<(FontKey, Au, FontInstanceFlags), FontInstanceKey>,
font_render_mode: Option<FontRenderMode>,
allow_mipmaps: bool,
@@ -1346,26 +1346,26 @@ impl YamlFrameReader {
dl: &mut DisplayListBuilder,
wrench: &mut Wrench,
yaml: &Yaml,
) {
let clip_rect = yaml["bounds"]
.as_rect()
.expect("scroll frame must have a bounds");
let content_size = yaml["content-size"].as_size().unwrap_or(clip_rect.size);
- let content_rect = LayerRect::new(clip_rect.origin, content_size);
+ let content_rect = LayoutRect::new(clip_rect.origin, content_size);
let numeric_id = yaml["id"].as_i64().map(|id| id as u64);
let complex_clips = self.to_complex_clip_regions(&yaml["complex"]);
let image_mask = self.to_image_mask(&yaml["image-mask"], wrench);
let external_id = yaml["scroll-offset"].as_point().map(|size| {
let id = ExternalScrollId((self.scroll_offsets.len() + 1) as u64, dl.pipeline_id);
- self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y));
+ self.scroll_offsets.insert(id, LayoutPoint::new(size.x, size.y));
id
});
let real_id = dl.define_scroll_frame(
external_id,
content_rect,
clip_rect,
complex_clips,
@@ -1536,17 +1536,17 @@ impl YamlFrameReader {
.unwrap_or(ScrollPolicy::Scrollable);
let glyph_raster_space = yaml["glyph-raster-space"]
.as_glyph_raster_space()
.unwrap_or(GlyphRasterSpace::Screen);
if is_root {
if let Some(size) = yaml["scroll-offset"].as_point() {
let external_id = ExternalScrollId(0, dl.pipeline_id);
- self.scroll_offsets.insert(external_id, LayerPoint::new(size.x, size.y));
+ self.scroll_offsets.insert(external_id, LayoutPoint::new(size.x, size.y));
}
}
let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
info.rect = bounds;
info.clip_rect = bounds;
dl.push_stacking_context(
--- a/gfx/wrench/src/yaml_frame_writer.rs
+++ b/gfx/wrench/src/yaml_frame_writer.rs
@@ -702,17 +702,17 @@ impl YamlFrameWriter {
*list_iterator = traversal;
}
let base = match list_iterator.next() {
Some(base) => base,
None => break,
};
let mut v = new_table();
- let info = base.get_layer_primitive_info(&LayoutVector2D::zero());
+ let info = base.get_layout_primitive_info(&LayoutVector2D::zero());
rect_node(&mut v, "bounds", &info.rect);
rect_node(&mut v, "clip-rect", &info.clip_rect);
if let Some(tag) = info.tag {
yaml_node(
&mut v,
"hit-testing-tag",
Yaml::Array(vec![Yaml::Integer(tag.0 as i64), Yaml::Integer(tag.1 as i64)])