зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1439565 - Update webrender to commit 8a19316a733a484bf9bafb8257e3008b1418bfe4. r=jrmuizel
MozReview-Commit-ID: BZIK3GEG0ER --HG-- extra : rebase_source : c24dbf123fe1732917e9fc57ee0ddfe2042892c4
This commit is contained in:
Родитель
17ab2350ee
Коммит
f22ca7ca1e
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#define VECS_PER_SPECIFIC_BRUSH 5
|
#define VECS_PER_SPECIFIC_BRUSH 1
|
||||||
#define FORCE_NO_PERSPECTIVE
|
#define FORCE_NO_PERSPECTIVE
|
||||||
|
|
||||||
#include shared,prim_shared,brush
|
#include shared,prim_shared,brush
|
||||||
|
@ -83,9 +83,10 @@ void brush_vs(
|
||||||
}
|
}
|
||||||
case 10: {
|
case 10: {
|
||||||
// Color Matrix
|
// Color Matrix
|
||||||
vec4 data[4] = fetch_from_resource_cache_4(prim_address + 1);
|
vec4 mat_data[4] = fetch_from_resource_cache_4(user_data.z);
|
||||||
vColorMat = mat4(amount, data[0], data[1], data[2]);
|
vec4 offset_data = fetch_from_resource_cache_1(user_data.z + 4);
|
||||||
vColorOffset = data[3];
|
vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]);
|
||||||
|
vColorOffset = offset_data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
|
|
@ -40,7 +40,12 @@ void brush_vs(
|
||||||
vUv.xy = mix(uv0, uv1, f);
|
vUv.xy = mix(uv0, uv1, f);
|
||||||
vUv.xy /= texture_size;
|
vUv.xy /= texture_size;
|
||||||
|
|
||||||
vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
|
// Handle case where the UV coords are inverted (e.g. from an
|
||||||
|
// external image).
|
||||||
|
vUvBounds = vec4(
|
||||||
|
min(uv0, uv1) + vec2(0.5),
|
||||||
|
max(uv0, uv1) - vec2(0.5)
|
||||||
|
) / texture_size.xyxy;
|
||||||
|
|
||||||
#ifdef WR_FEATURE_ALPHA_PASS
|
#ifdef WR_FEATURE_ALPHA_PASS
|
||||||
vLocalPos = vi.local_pos;
|
vLocalPos = vi.local_pos;
|
||||||
|
|
|
@ -119,38 +119,7 @@ void brush_vs(
|
||||||
|
|
||||||
#ifdef WR_FRAGMENT_SHADER
|
#ifdef WR_FRAGMENT_SHADER
|
||||||
|
|
||||||
#define MAGIC_WAVY_LINE_AA_SNAP 0.7
|
#define MAGIC_WAVY_LINE_AA_SNAP 0.5
|
||||||
|
|
||||||
float det(vec2 a, vec2 b) {
|
|
||||||
return a.x * b.y - b.x * a.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// From: http://research.microsoft.com/en-us/um/people/hoppe/ravg.pdf
|
|
||||||
vec2 get_distance_vector(vec2 b0, vec2 b1, vec2 b2) {
|
|
||||||
float a = det(b0, b2);
|
|
||||||
float b = 2.0 * det(b1, b0);
|
|
||||||
float d = 2.0 * det(b2, b1);
|
|
||||||
|
|
||||||
float f = b * d - a * a;
|
|
||||||
vec2 d21 = b2 - b1;
|
|
||||||
vec2 d10 = b1 - b0;
|
|
||||||
vec2 d20 = b2 - b0;
|
|
||||||
|
|
||||||
vec2 gf = 2.0 * (b *d21 + d * d10 + a * d20);
|
|
||||||
gf = vec2(gf.y,-gf.x);
|
|
||||||
vec2 pp = -f * gf / dot(gf, gf);
|
|
||||||
vec2 d0p = b0 - pp;
|
|
||||||
float ap = det(d0p, d20);
|
|
||||||
float bp = 2.0 * det(d10, d0p);
|
|
||||||
|
|
||||||
float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);
|
|
||||||
return mix(mix(b0, b1, t), mix(b1,b2,t), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Approximate distance from point to quadratic bezier.
|
|
||||||
float approx_distance(vec2 p, vec2 b0, vec2 b1, vec2 b2) {
|
|
||||||
return length(get_distance_vector(b0 - p, b1 - p, b2 - p));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 brush_fs() {
|
vec4 brush_fs() {
|
||||||
// Find the appropriate distance to apply the step over.
|
// Find the appropriate distance to apply the step over.
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#define VECS_PER_SPECIFIC_BRUSH 2
|
||||||
|
|
||||||
|
#include shared,prim_shared,brush
|
||||||
|
|
||||||
|
flat varying int vGradientAddress;
|
||||||
|
flat varying float vGradientRepeat;
|
||||||
|
|
||||||
|
flat varying vec2 vScaledDir;
|
||||||
|
flat varying vec2 vStartPoint;
|
||||||
|
|
||||||
|
varying vec2 vPos;
|
||||||
|
|
||||||
|
#ifdef WR_FEATURE_ALPHA_PASS
|
||||||
|
varying vec2 vLocalPos;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WR_VERTEX_SHADER
|
||||||
|
|
||||||
|
struct Gradient {
|
||||||
|
vec4 start_end_point;
|
||||||
|
vec4 extend_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
Gradient fetch_gradient(int address) {
|
||||||
|
vec4 data[2] = fetch_from_resource_cache_2(address);
|
||||||
|
return Gradient(data[0], data[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void brush_vs(
|
||||||
|
VertexInfo vi,
|
||||||
|
int prim_address,
|
||||||
|
RectWithSize local_rect,
|
||||||
|
ivec3 user_data,
|
||||||
|
PictureTask pic_task
|
||||||
|
) {
|
||||||
|
Gradient gradient = fetch_gradient(prim_address);
|
||||||
|
|
||||||
|
vPos = vi.local_pos - local_rect.p0;
|
||||||
|
|
||||||
|
vec2 start_point = gradient.start_end_point.xy;
|
||||||
|
vec2 end_point = gradient.start_end_point.zw;
|
||||||
|
vec2 dir = end_point - start_point;
|
||||||
|
|
||||||
|
vStartPoint = start_point;
|
||||||
|
vScaledDir = dir / dot(dir, dir);
|
||||||
|
|
||||||
|
vGradientAddress = user_data.x;
|
||||||
|
|
||||||
|
// Whether to repeat the gradient instead of clamping.
|
||||||
|
vGradientRepeat = float(int(gradient.extend_mode.x) != EXTEND_MODE_CLAMP);
|
||||||
|
|
||||||
|
#ifdef WR_FEATURE_ALPHA_PASS
|
||||||
|
vLocalPos = vi.local_pos;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WR_FRAGMENT_SHADER
|
||||||
|
vec4 brush_fs() {
|
||||||
|
float offset = dot(vPos - vStartPoint, vScaledDir);
|
||||||
|
|
||||||
|
vec4 color = sample_gradient(vGradientAddress,
|
||||||
|
offset,
|
||||||
|
vGradientRepeat);
|
||||||
|
|
||||||
|
#ifdef WR_FEATURE_ALPHA_PASS
|
||||||
|
color *= init_transform_fs(vLocalPos);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#define VECS_PER_SPECIFIC_BRUSH 5
|
#define VECS_PER_SPECIFIC_BRUSH 1
|
||||||
|
|
||||||
#include shared,prim_shared,brush
|
#include shared,prim_shared,brush
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#define VECS_PER_SPECIFIC_BRUSH 5
|
#define VECS_PER_SPECIFIC_BRUSH 1
|
||||||
|
|
||||||
#include shared,prim_shared,brush
|
#include shared,prim_shared,brush
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,12 @@ varying vec2 vLocalPos;
|
||||||
flat varying vec4 vUvBounds_YUV;
|
flat varying vec4 vUvBounds_YUV;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WR_FEATURE_TEXTURE_RECT
|
||||||
|
#define TEX_SIZE(sampler) vec2(1.0)
|
||||||
|
#else
|
||||||
|
#define TEX_SIZE(sampler) vec2(textureSize(sampler, 0).xy)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WR_VERTEX_SHADER
|
#ifdef WR_VERTEX_SHADER
|
||||||
void write_uv_rect(
|
void write_uv_rect(
|
||||||
int resource_id,
|
int resource_id,
|
||||||
|
@ -78,14 +84,14 @@ void brush_vs(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||||
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_Y, vUvBounds_Y);
|
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||||
write_uv_rect(user_data.y, f, vec2(textureSize(sColor1, 0).xy), vUv_U, vUvBounds_U);
|
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
|
||||||
write_uv_rect(user_data.z, f, vec2(textureSize(sColor2, 0).xy), vUv_V, vUvBounds_V);
|
write_uv_rect(user_data.z, f, TEX_SIZE(sColor2), vUv_V, vUvBounds_V);
|
||||||
#elif defined (WR_FEATURE_YUV_NV12)
|
#elif defined (WR_FEATURE_YUV_NV12)
|
||||||
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_Y, vUvBounds_Y);
|
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||||
write_uv_rect(user_data.y, f, vec2(textureSize(sColor1, 0).xy), vUv_UV, vUvBounds_UV);
|
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_UV, vUvBounds_UV);
|
||||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||||
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_YUV, vUvBounds_YUV);
|
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_YUV, vUvBounds_YUV);
|
||||||
#endif //WR_FEATURE_YUV_*
|
#endif //WR_FEATURE_YUV_*
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#define SUBPX_DIR_HORIZONTAL 1
|
#define SUBPX_DIR_HORIZONTAL 1
|
||||||
#define SUBPX_DIR_VERTICAL 2
|
#define SUBPX_DIR_VERTICAL 2
|
||||||
|
|
||||||
|
#define EPSILON 0.0001
|
||||||
|
|
||||||
uniform sampler2DArray sCacheA8;
|
uniform sampler2DArray sCacheA8;
|
||||||
uniform sampler2DArray sCacheRGBA8;
|
uniform sampler2DArray sCacheRGBA8;
|
||||||
|
|
||||||
|
@ -74,7 +76,6 @@ vec4[2] fetch_from_resource_cache_2(int address) {
|
||||||
#define VECS_PER_RENDER_TASK 3
|
#define VECS_PER_RENDER_TASK 3
|
||||||
#define VECS_PER_PRIM_HEADER 2
|
#define VECS_PER_PRIM_HEADER 2
|
||||||
#define VECS_PER_TEXT_RUN 3
|
#define VECS_PER_TEXT_RUN 3
|
||||||
#define VECS_PER_GRADIENT 3
|
|
||||||
#define VECS_PER_GRADIENT_STOP 2
|
#define VECS_PER_GRADIENT_STOP 2
|
||||||
|
|
||||||
uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes;
|
uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes;
|
||||||
|
@ -304,17 +305,6 @@ ClipArea fetch_clip_area(int index) {
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Gradient {
|
|
||||||
vec4 start_end_point;
|
|
||||||
vec4 tile_size_repeat;
|
|
||||||
vec4 extend_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
Gradient fetch_gradient(int address) {
|
|
||||||
vec4 data[3] = fetch_from_resource_cache_3(address);
|
|
||||||
return Gradient(data[0], data[1], data[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Glyph {
|
struct Glyph {
|
||||||
vec2 offset;
|
vec2 offset;
|
||||||
};
|
};
|
||||||
|
@ -748,7 +738,7 @@ void write_clip(vec2 global_pos, ClipArea area) {
|
||||||
|
|
||||||
#ifdef WR_FRAGMENT_SHADER
|
#ifdef WR_FRAGMENT_SHADER
|
||||||
|
|
||||||
/// Find the appropriate half range to apply the AA smoothstep over.
|
/// Find the appropriate half range to apply the AA approximation over.
|
||||||
/// This range represents a coefficient to go from one CSS pixel to half a device pixel.
|
/// This range represents a coefficient to go from one CSS pixel to half a device pixel.
|
||||||
float compute_aa_range(vec2 position) {
|
float compute_aa_range(vec2 position) {
|
||||||
// The constant factor is chosen to compensate for the fact that length(fw) is equal
|
// The constant factor is chosen to compensate for the fact that length(fw) is equal
|
||||||
|
@ -759,22 +749,41 @@ float compute_aa_range(vec2 position) {
|
||||||
// such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
|
// such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
|
||||||
// curves properly connect with non-antialiased vertical or horizontal lines, among other things.
|
// curves properly connect with non-antialiased vertical or horizontal lines, among other things.
|
||||||
//
|
//
|
||||||
// Using larger aa steps is quite common when rendering shapes with distance fields.
|
// Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
|
||||||
// It gives a smoother (although blurrier look) by extending the range that is smoothed
|
// indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
|
||||||
// to produce the anti aliasing. In our case, however, extending the range inside of
|
// a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
|
||||||
// the shape causes noticeable artifacts at the junction between an antialiased corner
|
// aliased corner and a straight edge.
|
||||||
// and a straight edge.
|
//
|
||||||
// We may want to adjust this constant in specific scenarios (for example keep the principled
|
// We may want to adjust this constant in specific scenarios (for example keep the principled
|
||||||
// value for straight edges where we want pixel-perfect equivalence with non antialiased lines
|
// value for straight edges where we want pixel-perfect equivalence with non antialiased lines
|
||||||
// when axis aligned, while selecting a larger and smoother aa range on curves).
|
// when axis aligned, while selecting a larger and smoother aa range on curves).
|
||||||
return 0.35355 * length(fwidth(position));
|
return 0.35355 * length(fwidth(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the blending coefficient to for distance antialiasing.
|
/// Return the blending coefficient for distance antialiasing.
|
||||||
///
|
///
|
||||||
/// 0.0 means inside the shape, 1.0 means outside.
|
/// 0.0 means inside the shape, 1.0 means outside.
|
||||||
|
///
|
||||||
|
/// This cubic polynomial approximates the area of a 1x1 pixel square under a
|
||||||
|
/// line, given the signed Euclidean distance from the center of the square to
|
||||||
|
/// that line. Calculating the *exact* area would require taking into account
|
||||||
|
/// not only this distance but also the angle of the line. However, in
|
||||||
|
/// practice, this complexity is not required, as the area is roughly the same
|
||||||
|
/// regardless of the angle.
|
||||||
|
///
|
||||||
|
/// The coefficients of this polynomial were determined through least-squares
|
||||||
|
/// regression and are accurate to within 2.16% of the total area of the pixel
|
||||||
|
/// square 95% of the time, with a maximum error of 3.53%.
|
||||||
|
///
|
||||||
|
/// See the comments in `compute_aa_range()` for more information on the
|
||||||
|
/// cutoff values of -0.5 and 0.5.
|
||||||
float distance_aa(float aa_range, float signed_distance) {
|
float distance_aa(float aa_range, float signed_distance) {
|
||||||
return 1.0 - smoothstep(-aa_range, aa_range, signed_distance);
|
float dist = 0.5 * signed_distance / aa_range;
|
||||||
|
if (dist <= -0.5 + EPSILON)
|
||||||
|
return 1.0;
|
||||||
|
if (dist >= 0.5 - EPSILON)
|
||||||
|
return 0.0;
|
||||||
|
return 0.5 + dist * (0.8431027 * dist * dist - 1.14453603);
|
||||||
}
|
}
|
||||||
|
|
||||||
float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {
|
float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/* 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,prim_shared
|
|
||||||
|
|
||||||
flat varying int vGradientAddress;
|
|
||||||
flat varying float vGradientRepeat;
|
|
||||||
|
|
||||||
flat varying vec2 vScaledDir;
|
|
||||||
flat varying vec2 vStartPoint;
|
|
||||||
|
|
||||||
flat varying vec2 vTileSize;
|
|
||||||
flat varying vec2 vTileRepeat;
|
|
||||||
|
|
||||||
varying vec2 vPos;
|
|
||||||
|
|
||||||
#ifdef WR_VERTEX_SHADER
|
|
||||||
void main(void) {
|
|
||||||
Primitive prim = load_primitive();
|
|
||||||
Gradient gradient = fetch_gradient(prim.specific_prim_address);
|
|
||||||
|
|
||||||
VertexInfo vi = write_vertex(prim.local_rect,
|
|
||||||
prim.local_clip_rect,
|
|
||||||
prim.z,
|
|
||||||
prim.scroll_node,
|
|
||||||
prim.task,
|
|
||||||
prim.local_rect);
|
|
||||||
|
|
||||||
vPos = vi.local_pos - prim.local_rect.p0;
|
|
||||||
|
|
||||||
vec2 start_point = gradient.start_end_point.xy;
|
|
||||||
vec2 end_point = gradient.start_end_point.zw;
|
|
||||||
vec2 dir = end_point - start_point;
|
|
||||||
|
|
||||||
vStartPoint = start_point;
|
|
||||||
vScaledDir = dir / dot(dir, dir);
|
|
||||||
|
|
||||||
vTileSize = gradient.tile_size_repeat.xy;
|
|
||||||
vTileRepeat = gradient.tile_size_repeat.zw;
|
|
||||||
|
|
||||||
vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
|
|
||||||
|
|
||||||
// Whether to repeat the gradient instead of clamping.
|
|
||||||
vGradientRepeat = float(int(gradient.extend_mode.x) != EXTEND_MODE_CLAMP);
|
|
||||||
|
|
||||||
write_clip(vi.screen_pos, prim.clip_area);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WR_FRAGMENT_SHADER
|
|
||||||
void main(void) {
|
|
||||||
vec2 pos = mod(vPos, vTileRepeat);
|
|
||||||
|
|
||||||
if (pos.x >= vTileSize.x ||
|
|
||||||
pos.y >= vTileSize.y) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
float offset = dot(pos - vStartPoint, vScaledDir);
|
|
||||||
|
|
||||||
vec4 color = sample_gradient(vGradientAddress,
|
|
||||||
offset,
|
|
||||||
vGradientRepeat);
|
|
||||||
|
|
||||||
oFragColor = color * do_clip();
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,119 +0,0 @@
|
||||||
/* 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,prim_shared
|
|
||||||
|
|
||||||
varying vec4 vColor;
|
|
||||||
|
|
||||||
varying vec2 vLocalPos;
|
|
||||||
|
|
||||||
#ifdef WR_VERTEX_SHADER
|
|
||||||
struct GradientStop {
|
|
||||||
vec4 color;
|
|
||||||
vec4 offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
GradientStop fetch_gradient_stop(int address) {
|
|
||||||
vec4 data[2] = fetch_from_resource_cache_2(address);
|
|
||||||
return GradientStop(data[0], data[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
Primitive prim = load_primitive();
|
|
||||||
Gradient gradient = fetch_gradient(prim.specific_prim_address);
|
|
||||||
|
|
||||||
vec4 abs_start_end_point = gradient.start_end_point + prim.local_rect.p0.xyxy;
|
|
||||||
|
|
||||||
int stop_address = prim.specific_prim_address +
|
|
||||||
VECS_PER_GRADIENT +
|
|
||||||
VECS_PER_GRADIENT_STOP * prim.user_data0;
|
|
||||||
|
|
||||||
GradientStop g0 = fetch_gradient_stop(stop_address);
|
|
||||||
GradientStop g1 = fetch_gradient_stop(stop_address + VECS_PER_GRADIENT_STOP);
|
|
||||||
|
|
||||||
RectWithSize segment_rect;
|
|
||||||
vec2 axis;
|
|
||||||
vec4 adjusted_color_g0 = g0.color;
|
|
||||||
vec4 adjusted_color_g1 = g1.color;
|
|
||||||
if (abs_start_end_point.y == abs_start_end_point.w) {
|
|
||||||
// Calculate the x coord of the gradient stops
|
|
||||||
vec2 g01_x = mix(abs_start_end_point.xx, abs_start_end_point.zz,
|
|
||||||
vec2(g0.offset.x, g1.offset.x));
|
|
||||||
|
|
||||||
// The gradient stops might exceed the geometry rect so clamp them
|
|
||||||
vec2 g01_x_clamped = clamp(g01_x,
|
|
||||||
prim.local_rect.p0.xx,
|
|
||||||
prim.local_rect.p0.xx + prim.local_rect.size.xx);
|
|
||||||
|
|
||||||
// Calculate the segment rect using the clamped coords
|
|
||||||
segment_rect.p0 = vec2(g01_x_clamped.x, prim.local_rect.p0.y);
|
|
||||||
segment_rect.size = vec2(g01_x_clamped.y - g01_x_clamped.x, prim.local_rect.size.y);
|
|
||||||
axis = vec2(1.0, 0.0);
|
|
||||||
|
|
||||||
// Adjust the stop colors by how much they were clamped
|
|
||||||
vec2 adjusted_offset = (g01_x_clamped - g01_x.xx) / (g01_x.y - g01_x.x);
|
|
||||||
adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
|
|
||||||
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
|
|
||||||
} else {
|
|
||||||
// Calculate the y coord of the gradient stops
|
|
||||||
vec2 g01_y = mix(abs_start_end_point.yy, abs_start_end_point.ww,
|
|
||||||
vec2(g0.offset.x, g1.offset.x));
|
|
||||||
|
|
||||||
// The gradient stops might exceed the geometry rect so clamp them
|
|
||||||
vec2 g01_y_clamped = clamp(g01_y,
|
|
||||||
prim.local_rect.p0.yy,
|
|
||||||
prim.local_rect.p0.yy + prim.local_rect.size.yy);
|
|
||||||
|
|
||||||
// Calculate the segment rect using the clamped coords
|
|
||||||
segment_rect.p0 = vec2(prim.local_rect.p0.x, g01_y_clamped.x);
|
|
||||||
segment_rect.size = vec2(prim.local_rect.size.x, g01_y_clamped.y - g01_y_clamped.x);
|
|
||||||
axis = vec2(0.0, 1.0);
|
|
||||||
|
|
||||||
// Adjust the stop colors by how much they were clamped
|
|
||||||
vec2 adjusted_offset = (g01_y_clamped - g01_y.xx) / (g01_y.y - g01_y.x);
|
|
||||||
adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
|
|
||||||
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WR_FEATURE_TRANSFORM
|
|
||||||
VertexInfo vi = write_transform_vertex(segment_rect,
|
|
||||||
prim.local_rect,
|
|
||||||
prim.local_clip_rect,
|
|
||||||
vec4(1.0),
|
|
||||||
prim.z,
|
|
||||||
prim.scroll_node,
|
|
||||||
prim.task,
|
|
||||||
true);
|
|
||||||
vLocalPos = vi.local_pos;
|
|
||||||
vec2 f = (vi.local_pos.xy - prim.local_rect.p0) / prim.local_rect.size;
|
|
||||||
#else
|
|
||||||
VertexInfo vi = write_vertex(segment_rect,
|
|
||||||
prim.local_clip_rect,
|
|
||||||
prim.z,
|
|
||||||
prim.scroll_node,
|
|
||||||
prim.task,
|
|
||||||
prim.local_rect);
|
|
||||||
|
|
||||||
vec2 f = (vi.local_pos - segment_rect.p0) / segment_rect.size;
|
|
||||||
vLocalPos = vi.local_pos;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
write_clip(vi.screen_pos, prim.clip_area);
|
|
||||||
|
|
||||||
vColor = mix(adjusted_color_g0, adjusted_color_g1, dot(f, axis));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WR_FRAGMENT_SHADER
|
|
||||||
void main(void) {
|
|
||||||
#ifdef WR_FEATURE_TRANSFORM
|
|
||||||
float alpha = init_transform_fs(vLocalPos);
|
|
||||||
#else
|
|
||||||
float alpha = 1.0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
alpha *= do_clip();
|
|
||||||
oFragColor = dither(vColor * alpha);
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -14,16 +14,9 @@
|
||||||
|
|
||||||
#include base
|
#include base
|
||||||
|
|
||||||
// The textureLod() doesn't support samplerExternalOES for WR_FEATURE_TEXTURE_EXTERNAL.
|
|
||||||
// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external_essl3.txt
|
|
||||||
//
|
|
||||||
// The textureLod() doesn't support sampler2DRect for WR_FEATURE_TEXTURE_RECT, too.
|
|
||||||
//
|
|
||||||
// Use texture() instead.
|
|
||||||
#if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_RECT) || defined(WR_FEATURE_TEXTURE_2D)
|
#if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_RECT) || defined(WR_FEATURE_TEXTURE_2D)
|
||||||
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
|
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
|
||||||
#else
|
#else
|
||||||
// In normal case, we use textureLod(). We haven't used the lod yet. So, we always pass 0.0 now.
|
|
||||||
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord)
|
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveIn
|
||||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
||||||
use plane_split::{BspSplitter, Polygon, Splitter};
|
use plane_split::{BspSplitter, Polygon, Splitter};
|
||||||
use prim_store::{ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
|
use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
|
||||||
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
|
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
|
||||||
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
|
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
|
||||||
use renderer::{BlendMode, ImageBufferKind};
|
use renderer::{BlendMode, ImageBufferKind};
|
||||||
|
@ -38,8 +38,6 @@ const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fff);
|
||||||
pub enum TransformBatchKind {
|
pub enum TransformBatchKind {
|
||||||
TextRun(GlyphFormat),
|
TextRun(GlyphFormat),
|
||||||
Image(ImageBufferKind),
|
Image(ImageBufferKind),
|
||||||
AlignedGradient,
|
|
||||||
AngleGradient,
|
|
||||||
BorderCorner,
|
BorderCorner,
|
||||||
BorderEdge,
|
BorderEdge,
|
||||||
}
|
}
|
||||||
|
@ -78,6 +76,7 @@ pub enum BrushBatchKind {
|
||||||
},
|
},
|
||||||
YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace),
|
YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace),
|
||||||
RadialGradient,
|
RadialGradient,
|
||||||
|
LinearGradient,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -682,6 +681,7 @@ impl AlphaBatchBuilder {
|
||||||
ctx.resource_cache,
|
ctx.resource_cache,
|
||||||
gpu_cache,
|
gpu_cache,
|
||||||
deferred_resolves,
|
deferred_resolves,
|
||||||
|
&ctx.cached_gradients,
|
||||||
) {
|
) {
|
||||||
self.add_brush_to_batch(
|
self.add_brush_to_batch(
|
||||||
brush,
|
brush,
|
||||||
|
@ -811,7 +811,7 @@ impl AlphaBatchBuilder {
|
||||||
let font_transform = if is_shadow {
|
let font_transform = if is_shadow {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(&scroll_node.transform)
|
Some(scroll_node.transform)
|
||||||
};
|
};
|
||||||
|
|
||||||
let font = text_cpu.get_font(
|
let font = text_cpu.get_font(
|
||||||
|
@ -969,6 +969,7 @@ impl AlphaBatchBuilder {
|
||||||
is_in_3d_context,
|
is_in_3d_context,
|
||||||
reference_frame_id,
|
reference_frame_id,
|
||||||
real_local_rect,
|
real_local_rect,
|
||||||
|
ref extra_gpu_data_handle,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
// If this picture is participating in a 3D rendering context,
|
// If this picture is participating in a 3D rendering context,
|
||||||
|
@ -977,8 +978,10 @@ impl AlphaBatchBuilder {
|
||||||
if is_in_3d_context {
|
if is_in_3d_context {
|
||||||
// Push into parent plane splitter.
|
// Push into parent plane splitter.
|
||||||
|
|
||||||
let real_xf = &ctx.clip_scroll_tree.nodes[&reference_frame_id].world_content_transform;
|
let real_xf = &ctx.clip_scroll_tree
|
||||||
|
.nodes[&reference_frame_id]
|
||||||
|
.world_content_transform
|
||||||
|
.into();
|
||||||
let polygon = make_polygon(
|
let polygon = make_polygon(
|
||||||
real_local_rect,
|
real_local_rect,
|
||||||
&real_xf,
|
&real_xf,
|
||||||
|
@ -1093,18 +1096,20 @@ impl AlphaBatchBuilder {
|
||||||
BatchTextures::render_target_cache(),
|
BatchTextures::render_target_cache(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let filter_mode = match filter {
|
let (filter_mode, extra_cache_address) = match filter {
|
||||||
FilterOp::Blur(..) => 0,
|
FilterOp::Blur(..) => (0, 0),
|
||||||
FilterOp::Contrast(..) => 1,
|
FilterOp::Contrast(..) => (1, 0),
|
||||||
FilterOp::Grayscale(..) => 2,
|
FilterOp::Grayscale(..) => (2, 0),
|
||||||
FilterOp::HueRotate(..) => 3,
|
FilterOp::HueRotate(..) => (3, 0),
|
||||||
FilterOp::Invert(..) => 4,
|
FilterOp::Invert(..) => (4, 0),
|
||||||
FilterOp::Saturate(..) => 5,
|
FilterOp::Saturate(..) => (5, 0),
|
||||||
FilterOp::Sepia(..) => 6,
|
FilterOp::Sepia(..) => (6, 0),
|
||||||
FilterOp::Brightness(..) => 7,
|
FilterOp::Brightness(..) => (7, 0),
|
||||||
FilterOp::Opacity(..) => 8,
|
FilterOp::Opacity(..) => (8, 0),
|
||||||
FilterOp::DropShadow(..) => 9,
|
FilterOp::DropShadow(..) => (9, 0),
|
||||||
FilterOp::ColorMatrix(..) => 10,
|
FilterOp::ColorMatrix(..) => {
|
||||||
|
(10, extra_gpu_data_handle.as_int(gpu_cache))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let instance = BrushInstance {
|
let instance = BrushInstance {
|
||||||
|
@ -1120,7 +1125,7 @@ impl AlphaBatchBuilder {
|
||||||
user_data: [
|
user_data: [
|
||||||
cache_task_address.0 as i32,
|
cache_task_address.0 as i32,
|
||||||
filter_mode,
|
filter_mode,
|
||||||
0,
|
extra_cache_address,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1206,28 +1211,6 @@ impl AlphaBatchBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrimitiveKind::AlignedGradient => {
|
|
||||||
let gradient_cpu =
|
|
||||||
&ctx.prim_store.cpu_gradients[prim_metadata.cpu_prim_index.0];
|
|
||||||
let kind = BatchKind::Transformable(
|
|
||||||
transform_kind,
|
|
||||||
TransformBatchKind::AlignedGradient,
|
|
||||||
);
|
|
||||||
let key = BatchKey::new(kind, non_segmented_blend_mode, no_textures);
|
|
||||||
let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
|
|
||||||
for part_index in 0 .. (gradient_cpu.stops_count - 1) {
|
|
||||||
batch.push(base_instance.build(part_index as i32, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PrimitiveKind::AngleGradient => {
|
|
||||||
let kind = BatchKind::Transformable(
|
|
||||||
transform_kind,
|
|
||||||
TransformBatchKind::AngleGradient,
|
|
||||||
);
|
|
||||||
let key = BatchKey::new(kind, non_segmented_blend_mode, no_textures);
|
|
||||||
let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
|
|
||||||
batch.push(base_instance.build(0, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,6 +1313,7 @@ impl BrushPrimitive {
|
||||||
resource_cache: &ResourceCache,
|
resource_cache: &ResourceCache,
|
||||||
gpu_cache: &mut GpuCache,
|
gpu_cache: &mut GpuCache,
|
||||||
deferred_resolves: &mut Vec<DeferredResolve>,
|
deferred_resolves: &mut Vec<DeferredResolve>,
|
||||||
|
cached_gradients: &[CachedGradient],
|
||||||
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {
|
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
BrushKind::Line { .. } => {
|
BrushKind::Line { .. } => {
|
||||||
|
@ -1376,7 +1360,8 @@ impl BrushPrimitive {
|
||||||
[0; 3],
|
[0; 3],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
BrushKind::RadialGradient { ref stops_handle, .. } => {
|
BrushKind::RadialGradient { gradient_index, .. } => {
|
||||||
|
let stops_handle = &cached_gradients[gradient_index.0].handle;
|
||||||
Some((
|
Some((
|
||||||
BrushBatchKind::RadialGradient,
|
BrushBatchKind::RadialGradient,
|
||||||
BatchTextures::no_texture(),
|
BatchTextures::no_texture(),
|
||||||
|
@ -1387,6 +1372,18 @@ impl BrushPrimitive {
|
||||||
],
|
],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
BrushKind::LinearGradient { gradient_index, .. } => {
|
||||||
|
let stops_handle = &cached_gradients[gradient_index.0].handle;
|
||||||
|
Some((
|
||||||
|
BrushBatchKind::LinearGradient,
|
||||||
|
BatchTextures::no_texture(),
|
||||||
|
[
|
||||||
|
stops_handle.as_int(gpu_cache),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
))
|
||||||
|
}
|
||||||
BrushKind::YuvImage { format, yuv_key, image_rendering, color_space } => {
|
BrushKind::YuvImage { format, yuv_key, image_rendering, color_space } => {
|
||||||
let mut textures = BatchTextures::no_texture();
|
let mut textures = BatchTextures::no_texture();
|
||||||
let mut uv_rect_addresses = [0; 3];
|
let mut uv_rect_addresses = [0; 3];
|
||||||
|
@ -1464,8 +1461,6 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimitiveKind::Border |
|
PrimitiveKind::Border |
|
||||||
PrimitiveKind::AlignedGradient |
|
|
||||||
PrimitiveKind::AngleGradient |
|
|
||||||
PrimitiveKind::Picture => {
|
PrimitiveKind::Picture => {
|
||||||
BlendMode::PremultipliedAlpha
|
BlendMode::PremultipliedAlpha
|
||||||
}
|
}
|
||||||
|
@ -1487,6 +1482,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
||||||
BrushKind::Line { .. } |
|
BrushKind::Line { .. } |
|
||||||
BrushKind::YuvImage { .. } |
|
BrushKind::YuvImage { .. } |
|
||||||
BrushKind::RadialGradient { .. } |
|
BrushKind::RadialGradient { .. } |
|
||||||
|
BrushKind::LinearGradient { .. } |
|
||||||
BrushKind::Picture => {
|
BrushKind::Picture => {
|
||||||
BlendMode::PremultipliedAlpha
|
BlendMode::PremultipliedAlpha
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
|
use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
|
||||||
use api::{ImageRendering, LayerRect, LayerToWorldTransform, LayoutPoint, LayoutVector2D};
|
use api::{ImageRendering, LayerRect, LayoutPoint, LayoutVector2D, LocalClip};
|
||||||
use api::LocalClip;
|
|
||||||
use border::{BorderCornerClipSource, ensure_no_corner_overlap};
|
use border::{BorderCornerClipSource, ensure_no_corner_overlap};
|
||||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||||
use ellipse::Ellipse;
|
use ellipse::Ellipse;
|
||||||
|
@ -13,7 +12,8 @@ use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
|
||||||
use gpu_types::ClipScrollNodeIndex;
|
use gpu_types::ClipScrollNodeIndex;
|
||||||
use prim_store::{ClipData, ImageMaskData};
|
use prim_store::{ClipData, ImageMaskData};
|
||||||
use resource_cache::{ImageRequest, ResourceCache};
|
use resource_cache::{ImageRequest, ResourceCache};
|
||||||
use util::{MaxRect, MatrixHelpers, calculate_screen_bounding_rect, extract_inner_rect_safe};
|
use util::{LayerToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
|
||||||
|
use util::extract_inner_rect_safe;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub type ClipStore = FreeList<ClipSources>;
|
pub type ClipStore = FreeList<ClipSources>;
|
||||||
|
@ -252,7 +252,7 @@ impl ClipSources {
|
||||||
|
|
||||||
pub fn get_screen_bounds(
|
pub fn get_screen_bounds(
|
||||||
&self,
|
&self,
|
||||||
transform: &LayerToWorldTransform,
|
transform: &LayerToWorldFastTransform,
|
||||||
device_pixel_scale: DevicePixelScale,
|
device_pixel_scale: DevicePixelScale,
|
||||||
) -> (DeviceIntRect, Option<DeviceIntRect>) {
|
) -> (DeviceIntRect, Option<DeviceIntRect>) {
|
||||||
// If this translation isn't axis aligned or has a perspective component, don't try to
|
// If this translation isn't axis aligned or has a perspective component, don't try to
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect};
|
use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect};
|
||||||
use api::{LayerSize, LayerToWorldTransform, LayerTransform, LayerVector2D, LayoutTransform};
|
use api::{LayerSize, LayerVector2D, LayoutTransform, LayoutVector2D, PipelineId, PropertyBinding};
|
||||||
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollEventPhase};
|
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyOffsetBounds};
|
||||||
use api::{ScrollLocation, ScrollSensitivity, StickyOffsetBounds, WorldPoint};
|
use api::WorldPoint;
|
||||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem};
|
use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem};
|
||||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState};
|
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState};
|
||||||
use euclid::SideOffsets2D;
|
use euclid::SideOffsets2D;
|
||||||
|
@ -15,7 +15,8 @@ use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData};
|
||||||
use resource_cache::ResourceCache;
|
use resource_cache::ResourceCache;
|
||||||
use scene::SceneProperties;
|
use scene::SceneProperties;
|
||||||
use spring::{DAMPING, STIFFNESS, Spring};
|
use spring::{DAMPING, STIFFNESS, Spring};
|
||||||
use util::{MatrixHelpers, TransformOrOffset, TransformedRectKind};
|
use util::{LayerToWorldFastTransform, LayerFastTransform, LayoutFastTransform};
|
||||||
|
use util::{TransformedRectKind};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
const CAN_OVERSCROLL: bool = true;
|
const CAN_OVERSCROLL: bool = true;
|
||||||
|
@ -91,10 +92,10 @@ pub struct ClipScrollNode {
|
||||||
/// between our reference frame and this node. For reference frames, we also include
|
/// between our reference frame and this node. For reference frames, we also include
|
||||||
/// whatever local transformation this reference frame provides. This can be combined
|
/// whatever local transformation this reference frame provides. This can be combined
|
||||||
/// with the local_viewport_rect to get its position in world space.
|
/// with the local_viewport_rect to get its position in world space.
|
||||||
pub world_viewport_transform: LayerToWorldTransform,
|
pub world_viewport_transform: LayerToWorldFastTransform,
|
||||||
|
|
||||||
/// World transform for content transformed by this node.
|
/// World transform for content transformed by this node.
|
||||||
pub world_content_transform: LayerToWorldTransform,
|
pub world_content_transform: LayerToWorldFastTransform,
|
||||||
|
|
||||||
/// Pipeline that this layer belongs to
|
/// Pipeline that this layer belongs to
|
||||||
pub pipeline_id: PipelineId,
|
pub pipeline_id: PipelineId,
|
||||||
|
@ -119,7 +120,7 @@ pub struct ClipScrollNode {
|
||||||
/// The transformation from the coordinate system which established our compatible coordinate
|
/// 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
|
/// system (same coordinate system id) and us. This can change via scroll offsets and via new
|
||||||
/// reference frame transforms.
|
/// reference frame transforms.
|
||||||
pub coordinate_system_relative_transform: TransformOrOffset,
|
pub coordinate_system_relative_transform: LayerFastTransform,
|
||||||
|
|
||||||
/// A linear ID / index of this clip-scroll node. Used as a reference to
|
/// 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.
|
/// pass to shaders, to allow them to fetch a given clip-scroll node.
|
||||||
|
@ -135,15 +136,15 @@ impl ClipScrollNode {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ClipScrollNode {
|
ClipScrollNode {
|
||||||
local_viewport_rect: *rect,
|
local_viewport_rect: *rect,
|
||||||
world_viewport_transform: LayerToWorldTransform::identity(),
|
world_viewport_transform: LayerToWorldFastTransform::identity(),
|
||||||
world_content_transform: LayerToWorldTransform::identity(),
|
world_content_transform: LayerToWorldFastTransform::identity(),
|
||||||
parent: parent_id,
|
parent: parent_id,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
node_type: node_type,
|
node_type: node_type,
|
||||||
invertible: true,
|
invertible: true,
|
||||||
coordinate_system_id: CoordinateSystemId(0),
|
coordinate_system_id: CoordinateSystemId(0),
|
||||||
coordinate_system_relative_transform: TransformOrOffset::zero(),
|
coordinate_system_relative_transform: LayerFastTransform::identity(),
|
||||||
node_data_index: ClipScrollNodeIndex(0),
|
node_data_index: ClipScrollNodeIndex(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,10 +178,12 @@ impl ClipScrollNode {
|
||||||
pipeline_id: PipelineId,
|
pipeline_id: PipelineId,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let identity = LayoutTransform::identity();
|
let identity = LayoutTransform::identity();
|
||||||
|
let source_perspective = source_perspective.map_or_else(
|
||||||
|
LayoutFastTransform::identity, |perspective| perspective.into());
|
||||||
let info = ReferenceFrameInfo {
|
let info = ReferenceFrameInfo {
|
||||||
resolved_transform: LayerTransform::identity(),
|
resolved_transform: LayerFastTransform::identity(),
|
||||||
source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)),
|
source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)),
|
||||||
source_perspective: source_perspective.unwrap_or(identity),
|
source_perspective: source_perspective,
|
||||||
origin_in_parent_reference_frame,
|
origin_in_parent_reference_frame,
|
||||||
invertible: true,
|
invertible: true,
|
||||||
};
|
};
|
||||||
|
@ -258,8 +261,8 @@ impl ClipScrollNode {
|
||||||
|
|
||||||
pub fn mark_uninvertible(&mut self) {
|
pub fn mark_uninvertible(&mut self) {
|
||||||
self.invertible = false;
|
self.invertible = false;
|
||||||
self.world_content_transform = LayerToWorldTransform::identity();
|
self.world_content_transform = LayerToWorldFastTransform::identity();
|
||||||
self.world_viewport_transform = LayerToWorldTransform::identity();
|
self.world_viewport_transform = LayerToWorldFastTransform::identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) {
|
pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) {
|
||||||
|
@ -274,7 +277,7 @@ impl ClipScrollNode {
|
||||||
TransformedRectKind::Complex
|
TransformedRectKind::Complex
|
||||||
};
|
};
|
||||||
let data = ClipScrollNodeData {
|
let data = ClipScrollNodeData {
|
||||||
transform: self.world_content_transform,
|
transform: self.world_content_transform.into(),
|
||||||
transform_kind: transform_kind as u32 as f32,
|
transform_kind: transform_kind as u32 as f32,
|
||||||
padding: [0.0; 3],
|
padding: [0.0; 3],
|
||||||
};
|
};
|
||||||
|
@ -303,9 +306,9 @@ impl ClipScrollNode {
|
||||||
|
|
||||||
self.update_transform(state, next_coordinate_system_id, scene_properties);
|
self.update_transform(state, next_coordinate_system_id, scene_properties);
|
||||||
|
|
||||||
// If this node is a reference frame, we check if the determinant is 0, which means it
|
// If this node is a reference frame, we check if it has a non-invertible matrix.
|
||||||
// has a non-invertible matrix. For non-reference-frames we assume that they will
|
// For non-reference-frames we assume that they will produce only additional
|
||||||
// produce only additional translations which should be invertible.
|
// translations which should be invertible.
|
||||||
match self.node_type {
|
match self.node_type {
|
||||||
NodeType::ReferenceFrame(info) if !info.invertible => {
|
NodeType::ReferenceFrame(info) if !info.invertible => {
|
||||||
self.mark_uninvertible();
|
self.mark_uninvertible();
|
||||||
|
@ -362,7 +365,7 @@ impl ClipScrollNode {
|
||||||
|
|
||||||
let mut clip_chain = clip_chains[state.parent_clip_chain_index.0].new_with_added_node(
|
let mut clip_chain = clip_chains[state.parent_clip_chain_index.0].new_with_added_node(
|
||||||
work_item,
|
work_item,
|
||||||
self.coordinate_system_relative_transform.apply(&local_outer_rect),
|
self.coordinate_system_relative_transform.transform_rect(&local_outer_rect),
|
||||||
screen_outer_rect,
|
screen_outer_rect,
|
||||||
screen_inner_rect,
|
screen_inner_rect,
|
||||||
);
|
);
|
||||||
|
@ -398,7 +401,7 @@ impl ClipScrollNode {
|
||||||
// provided by our own sticky positioning.
|
// provided by our own sticky positioning.
|
||||||
let accumulated_offset = state.parent_accumulated_scroll_offset + sticky_offset;
|
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 != LayerVector2D::zero() {
|
||||||
state.parent_reference_frame_transform.pre_translate(accumulated_offset.to_3d())
|
state.parent_reference_frame_transform.pre_translate(&accumulated_offset)
|
||||||
} else {
|
} else {
|
||||||
state.parent_reference_frame_transform
|
state.parent_reference_frame_transform
|
||||||
};
|
};
|
||||||
|
@ -407,7 +410,7 @@ impl ClipScrollNode {
|
||||||
// whatever scrolling offset we supply as well.
|
// whatever scrolling offset we supply as well.
|
||||||
let scroll_offset = self.scroll_offset();
|
let scroll_offset = self.scroll_offset();
|
||||||
self.world_content_transform = if scroll_offset != LayerVector2D::zero() {
|
self.world_content_transform = if scroll_offset != LayerVector2D::zero() {
|
||||||
self.world_viewport_transform.pre_translate(scroll_offset.to_3d())
|
self.world_viewport_transform.pre_translate(&scroll_offset)
|
||||||
} else {
|
} else {
|
||||||
self.world_viewport_transform
|
self.world_viewport_transform
|
||||||
};
|
};
|
||||||
|
@ -437,11 +440,9 @@ impl ClipScrollNode {
|
||||||
|
|
||||||
// Resolve the transform against any property bindings.
|
// Resolve the transform against any property bindings.
|
||||||
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
|
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
|
||||||
info.resolved_transform = LayerTransform::create_translation(
|
info.resolved_transform =
|
||||||
info.origin_in_parent_reference_frame.x,
|
LayerFastTransform::with_vector(info.origin_in_parent_reference_frame)
|
||||||
info.origin_in_parent_reference_frame.y,
|
.pre_mul(&source_transform.into())
|
||||||
0.0
|
|
||||||
).pre_mul(&source_transform)
|
|
||||||
.pre_mul(&info.source_perspective);
|
.pre_mul(&info.source_perspective);
|
||||||
|
|
||||||
// The transformation for this viewport in world coordinates is the transformation for
|
// The transformation for this viewport in world coordinates is the transformation for
|
||||||
|
@ -450,12 +451,14 @@ impl ClipScrollNode {
|
||||||
// whatever local transformation this reference frame provides. This can be combined
|
// whatever local transformation this reference frame provides. This can be combined
|
||||||
// with the local_viewport_rect to get its position in world space.
|
// with the local_viewport_rect to get its position in world space.
|
||||||
let relative_transform = info.resolved_transform
|
let relative_transform = info.resolved_transform
|
||||||
.post_translate(state.parent_accumulated_scroll_offset.to_3d());
|
.post_translate(state.parent_accumulated_scroll_offset)
|
||||||
self.world_viewport_transform = state.parent_reference_frame_transform
|
.to_transform()
|
||||||
.pre_mul(&relative_transform.with_destination::<LayerPixel>());
|
.with_destination::<LayerPixel>();
|
||||||
|
self.world_viewport_transform =
|
||||||
|
state.parent_reference_frame_transform.pre_mul(&relative_transform.into());
|
||||||
self.world_content_transform = self.world_viewport_transform;
|
self.world_content_transform = self.world_viewport_transform;
|
||||||
|
|
||||||
info.invertible = relative_transform.determinant() != 0.0;
|
info.invertible = self.world_viewport_transform.is_invertible();
|
||||||
if !info.invertible {
|
if !info.invertible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -465,7 +468,7 @@ impl ClipScrollNode {
|
||||||
match state.coordinate_system_relative_transform.update(relative_transform) {
|
match state.coordinate_system_relative_transform.update(relative_transform) {
|
||||||
Some(offset) => self.coordinate_system_relative_transform = offset,
|
Some(offset) => self.coordinate_system_relative_transform = offset,
|
||||||
None => {
|
None => {
|
||||||
self.coordinate_system_relative_transform = TransformOrOffset::zero();
|
self.coordinate_system_relative_transform = LayerFastTransform::identity();
|
||||||
state.current_coordinate_system_id = *next_coordinate_system_id;
|
state.current_coordinate_system_id = *next_coordinate_system_id;
|
||||||
next_coordinate_system_id.advance();
|
next_coordinate_system_id.advance();
|
||||||
}
|
}
|
||||||
|
@ -844,14 +847,14 @@ impl ScrollFrameInfo {
|
||||||
pub struct ReferenceFrameInfo {
|
pub struct ReferenceFrameInfo {
|
||||||
/// The transformation that establishes this reference frame, relative to the parent
|
/// The transformation that establishes this reference frame, relative to the parent
|
||||||
/// reference frame. The origin of the reference frame is included in the transformation.
|
/// reference frame. The origin of the reference frame is included in the transformation.
|
||||||
pub resolved_transform: LayerTransform,
|
pub resolved_transform: LayerFastTransform,
|
||||||
|
|
||||||
/// The source transform and perspective matrices provided by the stacking context
|
/// The source transform and perspective matrices provided by the stacking context
|
||||||
/// that forms this reference frame. We maintain the property binding information
|
/// 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
|
/// here so that we can resolve the animated transform and update the tree each
|
||||||
/// frame.
|
/// frame.
|
||||||
pub source_transform: PropertyBinding<LayoutTransform>,
|
pub source_transform: PropertyBinding<LayoutTransform>,
|
||||||
pub source_perspective: LayoutTransform,
|
pub source_perspective: LayoutFastTransform,
|
||||||
|
|
||||||
/// The original, not including the transform and relative to the parent reference frame,
|
/// 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
|
/// origin of this reference frame. This is already rolled into the `transform' property, but
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect};
|
use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect};
|
||||||
use api::{LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase};
|
use api::{LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLocation};
|
||||||
use api::{ScrollLocation, ScrollNodeState, WorldPoint};
|
use api::{ScrollNodeState, WorldPoint};
|
||||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore};
|
use clip::{ClipChain, ClipSourcesHandle, ClipStore};
|
||||||
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo};
|
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo};
|
||||||
use gpu_cache::GpuCache;
|
use gpu_cache::GpuCache;
|
||||||
|
@ -13,7 +13,7 @@ use internal_types::{FastHashMap, FastHashSet};
|
||||||
use print_tree::{PrintTree, PrintTreePrinter};
|
use print_tree::{PrintTree, PrintTreePrinter};
|
||||||
use resource_cache::ResourceCache;
|
use resource_cache::ResourceCache;
|
||||||
use scene::SceneProperties;
|
use scene::SceneProperties;
|
||||||
use util::TransformOrOffset;
|
use util::{LayerFastTransform, LayerToWorldFastTransform};
|
||||||
|
|
||||||
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ pub struct ClipScrollTree {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TransformUpdateState {
|
pub struct TransformUpdateState {
|
||||||
pub parent_reference_frame_transform: LayerToWorldTransform,
|
pub parent_reference_frame_transform: LayerToWorldFastTransform,
|
||||||
pub parent_accumulated_scroll_offset: LayerVector2D,
|
pub parent_accumulated_scroll_offset: LayerVector2D,
|
||||||
pub nearest_scrolling_ancestor_offset: LayerVector2D,
|
pub nearest_scrolling_ancestor_offset: LayerVector2D,
|
||||||
pub nearest_scrolling_ancestor_viewport: LayerRect,
|
pub nearest_scrolling_ancestor_viewport: LayerRect,
|
||||||
|
@ -103,7 +103,7 @@ pub struct TransformUpdateState {
|
||||||
pub current_coordinate_system_id: CoordinateSystemId,
|
pub current_coordinate_system_id: CoordinateSystemId,
|
||||||
|
|
||||||
/// Transform from the coordinate system that started this compatible coordinate system.
|
/// Transform from the coordinate system that started this compatible coordinate system.
|
||||||
pub coordinate_system_relative_transform: TransformOrOffset,
|
pub coordinate_system_relative_transform: LayerFastTransform,
|
||||||
|
|
||||||
/// True if this node is transformed by an invertible transform. If not, display items
|
/// 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
|
/// transformed by this node will not be displayed and display items not transformed by this
|
||||||
|
@ -329,17 +329,13 @@ impl ClipScrollTree {
|
||||||
|
|
||||||
let root_reference_frame_id = self.root_reference_frame_id();
|
let root_reference_frame_id = self.root_reference_frame_id();
|
||||||
let mut state = TransformUpdateState {
|
let mut state = TransformUpdateState {
|
||||||
parent_reference_frame_transform: LayerToWorldTransform::create_translation(
|
parent_reference_frame_transform: LayerVector2D::new(pan.x, pan.y).into(),
|
||||||
pan.x,
|
|
||||||
pan.y,
|
|
||||||
0.0,
|
|
||||||
),
|
|
||||||
parent_accumulated_scroll_offset: LayerVector2D::zero(),
|
parent_accumulated_scroll_offset: LayerVector2D::zero(),
|
||||||
nearest_scrolling_ancestor_offset: LayerVector2D::zero(),
|
nearest_scrolling_ancestor_offset: LayerVector2D::zero(),
|
||||||
nearest_scrolling_ancestor_viewport: LayerRect::zero(),
|
nearest_scrolling_ancestor_viewport: LayerRect::zero(),
|
||||||
parent_clip_chain_index: ClipChainIndex(0),
|
parent_clip_chain_index: ClipChainIndex(0),
|
||||||
current_coordinate_system_id: CoordinateSystemId::root(),
|
current_coordinate_system_id: CoordinateSystemId::root(),
|
||||||
coordinate_system_relative_transform: TransformOrOffset::zero(),
|
coordinate_system_relative_transform: LayerFastTransform::identity(),
|
||||||
invertible: true,
|
invertible: true,
|
||||||
};
|
};
|
||||||
let mut next_coordinate_system_id = state.current_coordinate_system_id.next();
|
let mut next_coordinate_system_id = state.current_coordinate_system_id.next();
|
||||||
|
|
|
@ -6,11 +6,10 @@ use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, ClipId,
|
||||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint};
|
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint};
|
||||||
use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId};
|
use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId};
|
||||||
use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering};
|
use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering};
|
||||||
use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerTransform};
|
use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D};
|
||||||
use api::{LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip};
|
use api::{LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip, PipelineId};
|
||||||
use api::{PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow};
|
use api::{PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow, TexelRect};
|
||||||
use api::{TexelRect, TileOffset, TransformStyle, WorldPoint, WorldToLayerTransform, YuvColorSpace};
|
use api::{TileOffset, TransformStyle, WorldPoint, YuvColorSpace, YuvData};
|
||||||
use api::YuvData;
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use border::ImageBorderSegment;
|
use border::ImageBorderSegment;
|
||||||
use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore};
|
use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore};
|
||||||
|
@ -19,12 +18,12 @@ use clip_scroll_tree::{ClipScrollTree, ClipChainIndex};
|
||||||
use euclid::{SideOffsets2D, vec2};
|
use euclid::{SideOffsets2D, vec2};
|
||||||
use frame::{FrameId, ClipIdToIndexMapper};
|
use frame::{FrameId, ClipIdToIndexMapper};
|
||||||
use glyph_rasterizer::FontInstance;
|
use glyph_rasterizer::FontInstance;
|
||||||
use gpu_cache::{GpuCache, GpuCacheHandle};
|
use gpu_cache::GpuCache;
|
||||||
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
|
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
|
||||||
use hit_test::{HitTester, HitTestingItem, HitTestingRun};
|
use hit_test::{HitTester, HitTestingItem, HitTestingRun};
|
||||||
use internal_types::{FastHashMap, FastHashSet};
|
use internal_types::{FastHashMap, FastHashSet};
|
||||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
||||||
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, GradientPrimitiveCpu};
|
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, CachedGradient, CachedGradientIndex};
|
||||||
use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer};
|
use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer};
|
||||||
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore};
|
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore};
|
||||||
use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
|
use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
|
||||||
|
@ -35,7 +34,7 @@ use scene::{ScenePipeline, SceneProperties};
|
||||||
use std::{mem, usize, f32};
|
use std::{mem, usize, f32};
|
||||||
use tiling::{CompositeOps, Frame, RenderPass, RenderTargetKind};
|
use tiling::{CompositeOps, Frame, RenderPass, RenderTargetKind};
|
||||||
use tiling::{RenderPassKind, RenderTargetContext, ScrollbarPrimitive};
|
use tiling::{RenderPassKind, RenderTargetContext, ScrollbarPrimitive};
|
||||||
use util::{self, MaxRect, pack_as_float, RectHelpers, recycle_vec};
|
use util::{self, MaxRect, RectHelpers, WorldToLayerFastTransform, recycle_vec};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ScrollbarInfo(pub ClipId, pub LayerRect);
|
pub struct ScrollbarInfo(pub ClipId, pub LayerRect);
|
||||||
|
@ -86,6 +85,7 @@ pub struct FrameBuilder {
|
||||||
pub clip_store: ClipStore,
|
pub clip_store: ClipStore,
|
||||||
hit_testing_runs: Vec<HitTestingRun>,
|
hit_testing_runs: Vec<HitTestingRun>,
|
||||||
pub config: FrameBuilderConfig,
|
pub config: FrameBuilderConfig,
|
||||||
|
pub cached_gradients: Vec<CachedGradient>,
|
||||||
|
|
||||||
// A stack of the current shadow primitives.
|
// A stack of the current shadow primitives.
|
||||||
// The sub-Vec stores a buffer of fast-path primitives to be appended on pop.
|
// The sub-Vec stores a buffer of fast-path primitives to be appended on pop.
|
||||||
|
@ -124,6 +124,7 @@ pub struct FrameState<'a> {
|
||||||
pub local_clip_rects: &'a mut Vec<LayerRect>,
|
pub local_clip_rects: &'a mut Vec<LayerRect>,
|
||||||
pub resource_cache: &'a mut ResourceCache,
|
pub resource_cache: &'a mut ResourceCache,
|
||||||
pub gpu_cache: &'a mut GpuCache,
|
pub gpu_cache: &'a mut GpuCache,
|
||||||
|
pub cached_gradients: &'a mut [CachedGradient],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PictureContext<'a> {
|
pub struct PictureContext<'a> {
|
||||||
|
@ -133,7 +134,7 @@ pub struct PictureContext<'a> {
|
||||||
pub original_reference_frame_id: Option<ClipId>,
|
pub original_reference_frame_id: Option<ClipId>,
|
||||||
pub display_list: &'a BuiltDisplayList,
|
pub display_list: &'a BuiltDisplayList,
|
||||||
pub draw_text_transformed: bool,
|
pub draw_text_transformed: bool,
|
||||||
pub inv_world_transform: Option<WorldToLayerTransform>,
|
pub inv_world_transform: Option<WorldToLayerFastTransform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PictureState {
|
pub struct PictureState {
|
||||||
|
@ -173,6 +174,7 @@ impl FrameBuilder {
|
||||||
FrameBuilder {
|
FrameBuilder {
|
||||||
hit_testing_runs: Vec::new(),
|
hit_testing_runs: Vec::new(),
|
||||||
shadow_prim_stack: Vec::new(),
|
shadow_prim_stack: Vec::new(),
|
||||||
|
cached_gradients: Vec::new(),
|
||||||
pending_shadow_contents: Vec::new(),
|
pending_shadow_contents: Vec::new(),
|
||||||
scrollbar_prims: Vec::new(),
|
scrollbar_prims: Vec::new(),
|
||||||
reference_frame_stack: Vec::new(),
|
reference_frame_stack: Vec::new(),
|
||||||
|
@ -201,6 +203,7 @@ impl FrameBuilder {
|
||||||
FrameBuilder {
|
FrameBuilder {
|
||||||
hit_testing_runs: recycle_vec(self.hit_testing_runs),
|
hit_testing_runs: recycle_vec(self.hit_testing_runs),
|
||||||
shadow_prim_stack: recycle_vec(self.shadow_prim_stack),
|
shadow_prim_stack: recycle_vec(self.shadow_prim_stack),
|
||||||
|
cached_gradients: recycle_vec(self.cached_gradients),
|
||||||
pending_shadow_contents: recycle_vec(self.pending_shadow_contents),
|
pending_shadow_contents: recycle_vec(self.pending_shadow_contents),
|
||||||
scrollbar_prims: recycle_vec(self.scrollbar_prims),
|
scrollbar_prims: recycle_vec(self.scrollbar_prims),
|
||||||
reference_frame_stack: recycle_vec(self.reference_frame_stack),
|
reference_frame_stack: recycle_vec(self.reference_frame_stack),
|
||||||
|
@ -673,11 +676,8 @@ impl FrameBuilder {
|
||||||
let root_id = clip_scroll_tree.root_reference_frame_id();
|
let root_id = clip_scroll_tree.root_reference_frame_id();
|
||||||
if let Some(root_node) = clip_scroll_tree.nodes.get_mut(&root_id) {
|
if let Some(root_node) = clip_scroll_tree.nodes.get_mut(&root_id) {
|
||||||
if let NodeType::ReferenceFrame(ref mut info) = root_node.node_type {
|
if let NodeType::ReferenceFrame(ref mut info) = root_node.node_type {
|
||||||
info.resolved_transform = LayerTransform::create_translation(
|
info.resolved_transform =
|
||||||
viewport_offset.x,
|
LayerVector2D::new(viewport_offset.x, viewport_offset.y).into();
|
||||||
viewport_offset.y,
|
|
||||||
0.0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1236,6 +1236,53 @@ impl FrameBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_gradient_impl(
|
||||||
|
&mut self,
|
||||||
|
clip_and_scroll: ScrollNodeAndClipChain,
|
||||||
|
info: &LayerPrimitiveInfo,
|
||||||
|
start_point: LayerPoint,
|
||||||
|
end_point: LayerPoint,
|
||||||
|
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
|
||||||
|
// just designate the reference orientation as start < end. Aligned gradient rendering
|
||||||
|
// manages to produce the same result regardless of orientation, so don't worry about
|
||||||
|
// reversing in that case.
|
||||||
|
let reverse_stops = start_point.x > end_point.x ||
|
||||||
|
(start_point.x == end_point.x && start_point.y > end_point.y);
|
||||||
|
|
||||||
|
// To get reftests exactly matching with reverse start/end
|
||||||
|
// points, it's necessary to reverse the gradient
|
||||||
|
// line in some cases.
|
||||||
|
let (sp, ep) = if reverse_stops {
|
||||||
|
(end_point, start_point)
|
||||||
|
} else {
|
||||||
|
(start_point, end_point)
|
||||||
|
};
|
||||||
|
|
||||||
|
let prim = BrushPrimitive::new(
|
||||||
|
BrushKind::LinearGradient {
|
||||||
|
stops_range: stops,
|
||||||
|
stops_count,
|
||||||
|
extend_mode,
|
||||||
|
reverse_stops,
|
||||||
|
start_point: sp,
|
||||||
|
end_point: ep,
|
||||||
|
gradient_index,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let prim = PrimitiveContainer::Brush(prim);
|
||||||
|
|
||||||
|
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_gradient(
|
pub fn add_gradient(
|
||||||
&mut self,
|
&mut self,
|
||||||
clip_and_scroll: ScrollNodeAndClipChain,
|
clip_and_scroll: ScrollNodeAndClipChain,
|
||||||
|
@ -1248,62 +1295,40 @@ impl FrameBuilder {
|
||||||
tile_size: LayerSize,
|
tile_size: LayerSize,
|
||||||
tile_spacing: LayerSize,
|
tile_spacing: LayerSize,
|
||||||
) {
|
) {
|
||||||
let tile_repeat = tile_size + tile_spacing;
|
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||||
let is_not_tiled = tile_repeat.width >= info.rect.size.width &&
|
self.cached_gradients.push(CachedGradient::new());
|
||||||
tile_repeat.height >= info.rect.size.height;
|
|
||||||
|
|
||||||
let aligned_and_fills_rect = (start_point.x == end_point.x &&
|
let prim_infos = info.decompose(
|
||||||
start_point.y.min(end_point.y) <= 0.0 &&
|
tile_size,
|
||||||
start_point.y.max(end_point.y) >= info.rect.size.height) ||
|
tile_spacing,
|
||||||
(start_point.y == end_point.y && start_point.x.min(end_point.x) <= 0.0 &&
|
64 * 64,
|
||||||
start_point.x.max(end_point.x) >= info.rect.size.width);
|
);
|
||||||
|
|
||||||
// Fast path for clamped, axis-aligned gradients, with gradient lines intersecting all of rect:
|
if prim_infos.is_empty() {
|
||||||
let aligned = extend_mode == ExtendMode::Clamp && is_not_tiled && aligned_and_fills_rect;
|
self.add_gradient_impl(
|
||||||
|
clip_and_scroll,
|
||||||
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
|
info,
|
||||||
// are also supplied in reverse that the rendered result will be equivalent. To do this,
|
start_point,
|
||||||
// a reference orientation for the gradient line must be chosen, somewhat arbitrarily, so
|
end_point,
|
||||||
// just designate the reference orientation as start < end. Aligned gradient rendering
|
stops,
|
||||||
// manages to produce the same result regardless of orientation, so don't worry about
|
|
||||||
// reversing in that case.
|
|
||||||
let reverse_stops = !aligned &&
|
|
||||||
(start_point.x > end_point.x ||
|
|
||||||
(start_point.x == end_point.x && start_point.y > end_point.y));
|
|
||||||
|
|
||||||
// To get reftests exactly matching with reverse start/end
|
|
||||||
// points, it's necessary to reverse the gradient
|
|
||||||
// line in some cases.
|
|
||||||
let (sp, ep) = if reverse_stops {
|
|
||||||
(end_point, start_point)
|
|
||||||
} else {
|
|
||||||
(start_point, end_point)
|
|
||||||
};
|
|
||||||
|
|
||||||
let gradient_cpu = GradientPrimitiveCpu {
|
|
||||||
stops_range: stops,
|
|
||||||
stops_count,
|
stops_count,
|
||||||
extend_mode,
|
extend_mode,
|
||||||
reverse_stops,
|
gradient_index,
|
||||||
gpu_blocks: [
|
);
|
||||||
[sp.x, sp.y, ep.x, ep.y].into(),
|
|
||||||
[
|
|
||||||
tile_size.width,
|
|
||||||
tile_size.height,
|
|
||||||
tile_repeat.width,
|
|
||||||
tile_repeat.height,
|
|
||||||
].into(),
|
|
||||||
[pack_as_float(extend_mode as u32), 0.0, 0.0, 0.0].into(),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
let prim = if aligned {
|
|
||||||
PrimitiveContainer::AlignedGradient(gradient_cpu)
|
|
||||||
} else {
|
} else {
|
||||||
PrimitiveContainer::AngleGradient(gradient_cpu)
|
for prim_info in prim_infos {
|
||||||
};
|
self.add_gradient_impl(
|
||||||
|
clip_and_scroll,
|
||||||
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
|
&prim_info,
|
||||||
|
start_point,
|
||||||
|
end_point,
|
||||||
|
stops,
|
||||||
|
stops_count,
|
||||||
|
extend_mode,
|
||||||
|
gradient_index,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_radial_gradient_impl(
|
fn add_radial_gradient_impl(
|
||||||
|
@ -1317,17 +1342,18 @@ impl FrameBuilder {
|
||||||
ratio_xy: f32,
|
ratio_xy: f32,
|
||||||
stops: ItemRange<GradientStop>,
|
stops: ItemRange<GradientStop>,
|
||||||
extend_mode: ExtendMode,
|
extend_mode: ExtendMode,
|
||||||
|
gradient_index: CachedGradientIndex,
|
||||||
) {
|
) {
|
||||||
let prim = BrushPrimitive::new(
|
let prim = BrushPrimitive::new(
|
||||||
BrushKind::RadialGradient {
|
BrushKind::RadialGradient {
|
||||||
stops_range: stops,
|
stops_range: stops,
|
||||||
extend_mode,
|
extend_mode,
|
||||||
stops_handle: GpuCacheHandle::new(),
|
|
||||||
start_center,
|
start_center,
|
||||||
end_center,
|
end_center,
|
||||||
start_radius,
|
start_radius,
|
||||||
end_radius,
|
end_radius,
|
||||||
ratio_xy,
|
ratio_xy,
|
||||||
|
gradient_index,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1354,6 +1380,9 @@ impl FrameBuilder {
|
||||||
tile_size: LayerSize,
|
tile_size: LayerSize,
|
||||||
tile_spacing: LayerSize,
|
tile_spacing: LayerSize,
|
||||||
) {
|
) {
|
||||||
|
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||||
|
self.cached_gradients.push(CachedGradient::new());
|
||||||
|
|
||||||
let prim_infos = info.decompose(
|
let prim_infos = info.decompose(
|
||||||
tile_size,
|
tile_size,
|
||||||
tile_spacing,
|
tile_spacing,
|
||||||
|
@ -1371,6 +1400,7 @@ impl FrameBuilder {
|
||||||
ratio_xy,
|
ratio_xy,
|
||||||
stops,
|
stops,
|
||||||
extend_mode,
|
extend_mode,
|
||||||
|
gradient_index,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
for prim_info in prim_infos {
|
for prim_info in prim_infos {
|
||||||
|
@ -1384,6 +1414,7 @@ impl FrameBuilder {
|
||||||
ratio_xy,
|
ratio_xy,
|
||||||
stops,
|
stops,
|
||||||
extend_mode,
|
extend_mode,
|
||||||
|
gradient_index,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1703,6 +1734,7 @@ impl FrameBuilder {
|
||||||
local_clip_rects,
|
local_clip_rects,
|
||||||
resource_cache,
|
resource_cache,
|
||||||
gpu_cache,
|
gpu_cache,
|
||||||
|
cached_gradients: &mut self.cached_gradients,
|
||||||
};
|
};
|
||||||
|
|
||||||
let pic_context = PictureContext {
|
let pic_context = PictureContext {
|
||||||
|
@ -1871,6 +1903,7 @@ impl FrameBuilder {
|
||||||
clip_scroll_tree,
|
clip_scroll_tree,
|
||||||
use_dual_source_blending,
|
use_dual_source_blending,
|
||||||
node_data: &node_data,
|
node_data: &node_data,
|
||||||
|
cached_gradients: &self.cached_gradients,
|
||||||
};
|
};
|
||||||
|
|
||||||
pass.build(
|
pass.build(
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag};
|
use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag};
|
||||||
use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LayerToWorldTransform, LocalClip, PipelineId};
|
use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LocalClip, PipelineId, WorldPoint};
|
||||||
use api::WorldPoint;
|
|
||||||
use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point};
|
use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point};
|
||||||
use clip_scroll_node::{ClipScrollNode, NodeType};
|
use clip_scroll_node::{ClipScrollNode, NodeType};
|
||||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollTree};
|
use clip_scroll_tree::{ClipChainIndex, ClipScrollTree};
|
||||||
use internal_types::FastHashMap;
|
use internal_types::FastHashMap;
|
||||||
use prim_store::ScrollNodeAndClipChain;
|
use prim_store::ScrollNodeAndClipChain;
|
||||||
|
use util::LayerToWorldFastTransform;
|
||||||
|
|
||||||
/// A copy of important clip scroll node data to use during hit testing. This a copy of
|
/// 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,
|
/// data from the ClipScrollTree that will persist as a new frame is under construction,
|
||||||
|
@ -20,10 +20,10 @@ pub struct HitTestClipScrollNode {
|
||||||
regions: Vec<HitTestRegion>,
|
regions: Vec<HitTestRegion>,
|
||||||
|
|
||||||
/// World transform for content transformed by this node.
|
/// World transform for content transformed by this node.
|
||||||
world_content_transform: LayerToWorldTransform,
|
world_content_transform: LayerToWorldFastTransform,
|
||||||
|
|
||||||
/// World viewport transform for content transformed by this node.
|
/// World viewport transform for content transformed by this node.
|
||||||
world_viewport_transform: LayerToWorldTransform,
|
world_viewport_transform: LayerToWorldFastTransform,
|
||||||
|
|
||||||
/// Origin of the viewport of the node, used to calculate node-relative positions.
|
/// Origin of the viewport of the node, used to calculate node-relative positions.
|
||||||
node_origin: LayerPoint,
|
node_origin: LayerPoint,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use api::{LayerRect, LayerToWorldScale, LayerVector2D, MixBlendMode, PipelineId}
|
||||||
use api::{PremultipliedColorF, Shadow};
|
use api::{PremultipliedColorF, Shadow};
|
||||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
|
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
|
||||||
use frame_builder::{FrameContext, FrameState, PictureState};
|
use frame_builder::{FrameContext, FrameState, PictureState};
|
||||||
use gpu_cache::GpuDataRequest;
|
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||||
use gpu_types::{BrushImageKind, PictureType};
|
use gpu_types::{BrushImageKind, PictureType};
|
||||||
use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
|
use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
|
||||||
use prim_store::ScrollNodeAndClipChain;
|
use prim_store::ScrollNodeAndClipChain;
|
||||||
|
@ -88,6 +88,10 @@ pub enum PictureKind {
|
||||||
// rendering context.
|
// rendering context.
|
||||||
reference_frame_id: ClipId,
|
reference_frame_id: ClipId,
|
||||||
real_local_rect: LayerRect,
|
real_local_rect: LayerRect,
|
||||||
|
// An optional cache handle for storing extra data
|
||||||
|
// in the GPU cache, depending on the type of
|
||||||
|
// picture.
|
||||||
|
extra_gpu_data_handle: GpuCacheHandle,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +221,7 @@ impl PicturePrimitive {
|
||||||
frame_output_pipeline_id,
|
frame_output_pipeline_id,
|
||||||
reference_frame_id,
|
reference_frame_id,
|
||||||
real_local_rect: LayerRect::zero(),
|
real_local_rect: LayerRect::zero(),
|
||||||
|
extra_gpu_data_handle: GpuCacheHandle::new(),
|
||||||
},
|
},
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
cull_children: true,
|
cull_children: true,
|
||||||
|
@ -333,6 +338,7 @@ impl PicturePrimitive {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
PictureKind::Image {
|
PictureKind::Image {
|
||||||
ref mut secondary_render_task_id,
|
ref mut secondary_render_task_id,
|
||||||
|
ref mut extra_gpu_data_handle,
|
||||||
composite_mode,
|
composite_mode,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
@ -429,6 +435,15 @@ impl PicturePrimitive {
|
||||||
pic_state.tasks.extend(pic_state_for_children.tasks);
|
pic_state.tasks.extend(pic_state_for_children.tasks);
|
||||||
self.surface = None;
|
self.surface = None;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if let FilterOp::ColorMatrix(m) = filter {
|
||||||
|
if let Some(mut request) = frame_state.gpu_cache.request(extra_gpu_data_handle) {
|
||||||
|
for i in 0..5 {
|
||||||
|
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let picture_task = RenderTask::new_picture(
|
let picture_task = RenderTask::new_picture(
|
||||||
RenderTaskLocation::Dynamic(None, prim_screen_rect.size),
|
RenderTaskLocation::Dynamic(None, prim_screen_rect.size),
|
||||||
prim_index,
|
prim_index,
|
||||||
|
@ -594,17 +609,10 @@ impl PicturePrimitive {
|
||||||
// making this more efficient for the common case.
|
// making this more efficient for the common case.
|
||||||
match self.kind {
|
match self.kind {
|
||||||
PictureKind::TextShadow { .. } => {
|
PictureKind::TextShadow { .. } => {
|
||||||
for _ in 0 .. 5 {
|
|
||||||
request.push([0.0; 4]);
|
request.push([0.0; 4]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
PictureKind::Image { composite_mode, .. } => {
|
PictureKind::Image { composite_mode, .. } => {
|
||||||
match composite_mode {
|
match composite_mode {
|
||||||
Some(PictureCompositeMode::Filter(FilterOp::ColorMatrix(m))) => {
|
|
||||||
for i in 0..5 {
|
|
||||||
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(PictureCompositeMode::Filter(filter)) => {
|
Some(PictureCompositeMode::Filter(filter)) => {
|
||||||
let amount = match filter {
|
let amount = match filter {
|
||||||
FilterOp::Contrast(amount) => amount,
|
FilterOp::Contrast(amount) => amount,
|
||||||
|
@ -623,23 +631,14 @@ impl PicturePrimitive {
|
||||||
};
|
};
|
||||||
|
|
||||||
request.push([amount, 1.0 - amount, 0.0, 0.0]);
|
request.push([amount, 1.0 - amount, 0.0, 0.0]);
|
||||||
|
|
||||||
for _ in 0 .. 4 {
|
|
||||||
request.push([0.0; 4]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
for _ in 0 .. 5 {
|
|
||||||
request.push([0.0; 4]);
|
request.push([0.0; 4]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
PictureKind::BoxShadow { color, .. } => {
|
PictureKind::BoxShadow { color, .. } => {
|
||||||
request.push(color.premultiplied());
|
request.push(color.premultiplied());
|
||||||
for _ in 0 .. 4 {
|
|
||||||
request.push([0.0; 4]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipId, ClipMode, ColorF, C
|
||||||
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode};
|
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode};
|
||||||
use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
|
use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
|
||||||
use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation};
|
use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation};
|
||||||
use api::{LineStyle, PremultipliedColorF, WorldToLayerTransform, YuvColorSpace, YuvFormat};
|
use api::{LineStyle, PremultipliedColorF, YuvColorSpace, YuvFormat};
|
||||||
use border::{BorderCornerInstance, BorderEdgeKind};
|
use border::{BorderCornerInstance, BorderEdgeKind};
|
||||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||||
use clip_scroll_node::ClipScrollNode;
|
use clip_scroll_node::ClipScrollNode;
|
||||||
|
@ -25,11 +25,11 @@ use resource_cache::{CacheItem, ImageProperties, ImageRequest, ResourceCache};
|
||||||
use segment::SegmentBuilder;
|
use segment::SegmentBuilder;
|
||||||
use std::{mem, usize};
|
use std::{mem, usize};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use util::{MatrixHelpers, calculate_screen_bounding_rect, pack_as_float};
|
use util::{MatrixHelpers, WorldToLayerFastTransform, calculate_screen_bounding_rect};
|
||||||
use util::recycle_vec;
|
use util::{pack_as_float, recycle_vec};
|
||||||
|
|
||||||
|
|
||||||
const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0;
|
const MIN_BRUSH_SPLIT_AREA: f32 = 256.0 * 256.0;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub struct ScrollNodeAndClipChain {
|
pub struct ScrollNodeAndClipChain {
|
||||||
|
@ -69,9 +69,20 @@ impl PrimitiveOpacity {
|
||||||
is_opaque: alpha == 1.0,
|
is_opaque: alpha == 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn accumulate(&mut self, alpha: f32) {
|
#[derive(Debug, Copy, Clone)]
|
||||||
self.is_opaque = self.is_opaque && alpha == 1.0;
|
pub struct CachedGradientIndex(pub usize);
|
||||||
|
|
||||||
|
pub struct CachedGradient {
|
||||||
|
pub handle: GpuCacheHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CachedGradient {
|
||||||
|
pub fn new() -> CachedGradient {
|
||||||
|
CachedGradient {
|
||||||
|
handle: GpuCacheHandle::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +135,6 @@ pub enum PrimitiveKind {
|
||||||
TextRun,
|
TextRun,
|
||||||
Image,
|
Image,
|
||||||
Border,
|
Border,
|
||||||
AlignedGradient,
|
|
||||||
AngleGradient,
|
|
||||||
Picture,
|
Picture,
|
||||||
Brush,
|
Brush,
|
||||||
}
|
}
|
||||||
|
@ -211,14 +220,23 @@ pub enum BrushKind {
|
||||||
image_rendering: ImageRendering,
|
image_rendering: ImageRendering,
|
||||||
},
|
},
|
||||||
RadialGradient {
|
RadialGradient {
|
||||||
|
gradient_index: CachedGradientIndex,
|
||||||
stops_range: ItemRange<GradientStop>,
|
stops_range: ItemRange<GradientStop>,
|
||||||
extend_mode: ExtendMode,
|
extend_mode: ExtendMode,
|
||||||
stops_handle: GpuCacheHandle,
|
|
||||||
start_center: LayerPoint,
|
start_center: LayerPoint,
|
||||||
end_center: LayerPoint,
|
end_center: LayerPoint,
|
||||||
start_radius: f32,
|
start_radius: f32,
|
||||||
end_radius: f32,
|
end_radius: f32,
|
||||||
ratio_xy: 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +247,8 @@ impl BrushKind {
|
||||||
BrushKind::Picture |
|
BrushKind::Picture |
|
||||||
BrushKind::Image { .. } |
|
BrushKind::Image { .. } |
|
||||||
BrushKind::YuvImage { .. } |
|
BrushKind::YuvImage { .. } |
|
||||||
BrushKind::RadialGradient { .. } => true,
|
BrushKind::RadialGradient { .. } |
|
||||||
|
BrushKind::LinearGradient { .. } => true,
|
||||||
|
|
||||||
BrushKind::Mask { .. } |
|
BrushKind::Mask { .. } |
|
||||||
BrushKind::Clear |
|
BrushKind::Clear |
|
||||||
|
@ -359,6 +378,20 @@ impl BrushPrimitive {
|
||||||
0.0,
|
0.0,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
BrushKind::LinearGradient { start_point, end_point, extend_mode, .. } => {
|
||||||
|
request.push([
|
||||||
|
start_point.x,
|
||||||
|
start_point.y,
|
||||||
|
end_point.x,
|
||||||
|
end_point.y,
|
||||||
|
]);
|
||||||
|
request.push([
|
||||||
|
pack_as_float(extend_mode as u32),
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
]);
|
||||||
|
}
|
||||||
BrushKind::RadialGradient { start_center, end_center, start_radius, end_radius, ratio_xy, extend_mode, .. } => {
|
BrushKind::RadialGradient { start_center, end_center, start_radius, end_radius, ratio_xy, extend_mode, .. } => {
|
||||||
request.push([
|
request.push([
|
||||||
start_center.x,
|
start_center.x,
|
||||||
|
@ -432,46 +465,6 @@ impl ToGpuBlocks for BorderPrimitiveCpu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct GradientPrimitiveCpu {
|
|
||||||
pub stops_range: ItemRange<GradientStop>,
|
|
||||||
pub stops_count: usize,
|
|
||||||
pub extend_mode: ExtendMode,
|
|
||||||
pub reverse_stops: bool,
|
|
||||||
pub gpu_blocks: [GpuBlockData; 3],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GradientPrimitiveCpu {
|
|
||||||
fn build_gpu_blocks_for_aligned(
|
|
||||||
&self,
|
|
||||||
display_list: &BuiltDisplayList,
|
|
||||||
mut request: GpuDataRequest,
|
|
||||||
) -> PrimitiveOpacity {
|
|
||||||
let mut opacity = PrimitiveOpacity::opaque();
|
|
||||||
request.extend_from_slice(&self.gpu_blocks);
|
|
||||||
let src_stops = display_list.get(self.stops_range);
|
|
||||||
|
|
||||||
for src in src_stops {
|
|
||||||
request.push(src.color.premultiplied());
|
|
||||||
request.push([src.offset, 0.0, 0.0, 0.0]);
|
|
||||||
opacity.accumulate(src.color.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
opacity
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_gpu_blocks_for_angle_radial(
|
|
||||||
&self,
|
|
||||||
display_list: &BuiltDisplayList,
|
|
||||||
mut request: GpuDataRequest,
|
|
||||||
) {
|
|
||||||
request.extend_from_slice(&self.gpu_blocks);
|
|
||||||
|
|
||||||
let gradient_builder = GradientGpuBlockBuilder::new(self.stops_range, display_list);
|
|
||||||
gradient_builder.build(self.reverse_stops, &mut request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The gradient entry index for the first color stop
|
// The gradient entry index for the first color stop
|
||||||
pub const GRADIENT_DATA_FIRST_STOP: usize = 0;
|
pub const GRADIENT_DATA_FIRST_STOP: usize = 0;
|
||||||
// The gradient entry index for the last color stop
|
// The gradient entry index for the last color stop
|
||||||
|
@ -670,7 +663,7 @@ impl TextRunPrimitiveCpu {
|
||||||
pub fn get_font(
|
pub fn get_font(
|
||||||
&self,
|
&self,
|
||||||
device_pixel_scale: DevicePixelScale,
|
device_pixel_scale: DevicePixelScale,
|
||||||
transform: Option<&LayerToWorldTransform>,
|
transform: Option<LayerToWorldTransform>,
|
||||||
) -> FontInstance {
|
) -> FontInstance {
|
||||||
let mut font = self.font.clone();
|
let mut font = self.font.clone();
|
||||||
font.size = font.size.scale_by(device_pixel_scale.0);
|
font.size = font.size.scale_by(device_pixel_scale.0);
|
||||||
|
@ -678,7 +671,7 @@ impl TextRunPrimitiveCpu {
|
||||||
if transform.has_perspective_component() || !transform.has_2d_inverse() {
|
if transform.has_perspective_component() || !transform.has_2d_inverse() {
|
||||||
font.render_mode = font.render_mode.limit_by(FontRenderMode::Alpha);
|
font.render_mode = font.render_mode.limit_by(FontRenderMode::Alpha);
|
||||||
} else {
|
} else {
|
||||||
font.transform = FontTransform::from(transform).quantize();
|
font.transform = FontTransform::from(&transform).quantize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font
|
font
|
||||||
|
@ -688,7 +681,7 @@ impl TextRunPrimitiveCpu {
|
||||||
&mut self,
|
&mut self,
|
||||||
resource_cache: &mut ResourceCache,
|
resource_cache: &mut ResourceCache,
|
||||||
device_pixel_scale: DevicePixelScale,
|
device_pixel_scale: DevicePixelScale,
|
||||||
transform: Option<&LayerToWorldTransform>,
|
transform: Option<LayerToWorldTransform>,
|
||||||
display_list: &BuiltDisplayList,
|
display_list: &BuiltDisplayList,
|
||||||
gpu_cache: &mut GpuCache,
|
gpu_cache: &mut GpuCache,
|
||||||
) {
|
) {
|
||||||
|
@ -937,8 +930,6 @@ pub enum PrimitiveContainer {
|
||||||
TextRun(TextRunPrimitiveCpu),
|
TextRun(TextRunPrimitiveCpu),
|
||||||
Image(ImagePrimitiveCpu),
|
Image(ImagePrimitiveCpu),
|
||||||
Border(BorderPrimitiveCpu),
|
Border(BorderPrimitiveCpu),
|
||||||
AlignedGradient(GradientPrimitiveCpu),
|
|
||||||
AngleGradient(GradientPrimitiveCpu),
|
|
||||||
Picture(PicturePrimitive),
|
Picture(PicturePrimitive),
|
||||||
Brush(BrushPrimitive),
|
Brush(BrushPrimitive),
|
||||||
}
|
}
|
||||||
|
@ -949,7 +940,6 @@ pub struct PrimitiveStore {
|
||||||
pub cpu_text_runs: Vec<TextRunPrimitiveCpu>,
|
pub cpu_text_runs: Vec<TextRunPrimitiveCpu>,
|
||||||
pub cpu_pictures: Vec<PicturePrimitive>,
|
pub cpu_pictures: Vec<PicturePrimitive>,
|
||||||
pub cpu_images: Vec<ImagePrimitiveCpu>,
|
pub cpu_images: Vec<ImagePrimitiveCpu>,
|
||||||
pub cpu_gradients: Vec<GradientPrimitiveCpu>,
|
|
||||||
pub cpu_metadata: Vec<PrimitiveMetadata>,
|
pub cpu_metadata: Vec<PrimitiveMetadata>,
|
||||||
pub cpu_borders: Vec<BorderPrimitiveCpu>,
|
pub cpu_borders: Vec<BorderPrimitiveCpu>,
|
||||||
}
|
}
|
||||||
|
@ -962,7 +952,6 @@ impl PrimitiveStore {
|
||||||
cpu_text_runs: Vec::new(),
|
cpu_text_runs: Vec::new(),
|
||||||
cpu_pictures: Vec::new(),
|
cpu_pictures: Vec::new(),
|
||||||
cpu_images: Vec::new(),
|
cpu_images: Vec::new(),
|
||||||
cpu_gradients: Vec::new(),
|
|
||||||
cpu_borders: Vec::new(),
|
cpu_borders: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -974,7 +963,6 @@ impl PrimitiveStore {
|
||||||
cpu_text_runs: recycle_vec(self.cpu_text_runs),
|
cpu_text_runs: recycle_vec(self.cpu_text_runs),
|
||||||
cpu_pictures: recycle_vec(self.cpu_pictures),
|
cpu_pictures: recycle_vec(self.cpu_pictures),
|
||||||
cpu_images: recycle_vec(self.cpu_images),
|
cpu_images: recycle_vec(self.cpu_images),
|
||||||
cpu_gradients: recycle_vec(self.cpu_gradients),
|
|
||||||
cpu_borders: recycle_vec(self.cpu_borders),
|
cpu_borders: recycle_vec(self.cpu_borders),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1015,6 +1003,7 @@ impl PrimitiveStore {
|
||||||
BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
|
BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
|
||||||
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
|
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
|
||||||
BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
|
BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
|
||||||
|
BrushKind::LinearGradient { .. } => PrimitiveOpacity::translucent(),
|
||||||
BrushKind::Picture => {
|
BrushKind::Picture => {
|
||||||
// TODO(gw): This is not currently used. In the future
|
// TODO(gw): This is not currently used. In the future
|
||||||
// we should detect opaque pictures.
|
// we should detect opaque pictures.
|
||||||
|
@ -1077,29 +1066,6 @@ impl PrimitiveStore {
|
||||||
self.cpu_borders.push(border_cpu);
|
self.cpu_borders.push(border_cpu);
|
||||||
metadata
|
metadata
|
||||||
}
|
}
|
||||||
PrimitiveContainer::AlignedGradient(gradient_cpu) => {
|
|
||||||
let metadata = PrimitiveMetadata {
|
|
||||||
opacity: PrimitiveOpacity::translucent(),
|
|
||||||
prim_kind: PrimitiveKind::AlignedGradient,
|
|
||||||
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()),
|
|
||||||
..base_metadata
|
|
||||||
};
|
|
||||||
|
|
||||||
self.cpu_gradients.push(gradient_cpu);
|
|
||||||
metadata
|
|
||||||
}
|
|
||||||
PrimitiveContainer::AngleGradient(gradient_cpu) => {
|
|
||||||
let metadata = PrimitiveMetadata {
|
|
||||||
// TODO: calculate if the gradient is actually opaque
|
|
||||||
opacity: PrimitiveOpacity::translucent(),
|
|
||||||
prim_kind: PrimitiveKind::AngleGradient,
|
|
||||||
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()),
|
|
||||||
..base_metadata
|
|
||||||
};
|
|
||||||
|
|
||||||
self.cpu_gradients.push(gradient_cpu);
|
|
||||||
metadata
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.cpu_metadata.push(metadata);
|
self.cpu_metadata.push(metadata);
|
||||||
|
@ -1146,7 +1112,7 @@ impl PrimitiveStore {
|
||||||
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
|
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||||
// The transform only makes sense for screen space rasterization
|
// The transform only makes sense for screen space rasterization
|
||||||
let transform = if pic_context.draw_text_transformed {
|
let transform = if pic_context.draw_text_transformed {
|
||||||
Some(&prim_run_context.scroll_node.world_content_transform)
|
Some(prim_run_context.scroll_node.world_content_transform.into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -1304,7 +1270,8 @@ impl PrimitiveStore {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BrushKind::RadialGradient { ref mut stops_handle, stops_range, .. } => {
|
BrushKind::RadialGradient { gradient_index, stops_range, .. } => {
|
||||||
|
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
|
||||||
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
|
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
|
||||||
let gradient_builder = GradientGpuBlockBuilder::new(
|
let gradient_builder = GradientGpuBlockBuilder::new(
|
||||||
stops_range,
|
stops_range,
|
||||||
|
@ -1316,6 +1283,19 @@ impl PrimitiveStore {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BrushKind::LinearGradient { gradient_index, stops_range, reverse_stops, .. } => {
|
||||||
|
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
|
||||||
|
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
|
||||||
|
let gradient_builder = GradientGpuBlockBuilder::new(
|
||||||
|
stops_range,
|
||||||
|
pic_context.display_list,
|
||||||
|
);
|
||||||
|
gradient_builder.build(
|
||||||
|
reverse_stops,
|
||||||
|
&mut request,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
BrushKind::Mask { .. } |
|
BrushKind::Mask { .. } |
|
||||||
BrushKind::Solid { .. } |
|
BrushKind::Solid { .. } |
|
||||||
BrushKind::Clear |
|
BrushKind::Clear |
|
||||||
|
@ -1323,8 +1303,6 @@ impl PrimitiveStore {
|
||||||
BrushKind::Picture { .. } => {}
|
BrushKind::Picture { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrimitiveKind::AlignedGradient |
|
|
||||||
PrimitiveKind::AngleGradient => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this GPU resource as required for this frame.
|
// Mark this GPU resource as required for this frame.
|
||||||
|
@ -1342,20 +1320,6 @@ impl PrimitiveStore {
|
||||||
let image = &self.cpu_images[metadata.cpu_prim_index.0];
|
let image = &self.cpu_images[metadata.cpu_prim_index.0];
|
||||||
image.write_gpu_blocks(request);
|
image.write_gpu_blocks(request);
|
||||||
}
|
}
|
||||||
PrimitiveKind::AlignedGradient => {
|
|
||||||
let gradient = &self.cpu_gradients[metadata.cpu_prim_index.0];
|
|
||||||
metadata.opacity = gradient.build_gpu_blocks_for_aligned(
|
|
||||||
pic_context.display_list,
|
|
||||||
request,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
PrimitiveKind::AngleGradient => {
|
|
||||||
let gradient = &self.cpu_gradients[metadata.cpu_prim_index.0];
|
|
||||||
gradient.build_gpu_blocks_for_angle_radial(
|
|
||||||
pic_context.display_list,
|
|
||||||
request,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
PrimitiveKind::TextRun => {
|
PrimitiveKind::TextRun => {
|
||||||
let text = &self.cpu_text_runs[metadata.cpu_prim_index.0];
|
let text = &self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||||
text.write_gpu_blocks(&mut request);
|
text.write_gpu_blocks(&mut request);
|
||||||
|
@ -1471,14 +1435,14 @@ impl PrimitiveStore {
|
||||||
let local_clip_rect = if clip_item.scroll_node_data_index == prim_run_context.scroll_node.node_data_index {
|
let local_clip_rect = if clip_item.scroll_node_data_index == prim_run_context.scroll_node.node_data_index {
|
||||||
local_clip_rect
|
local_clip_rect
|
||||||
} else {
|
} else {
|
||||||
let clip_transform_data = &frame_context
|
let clip_transform = frame_context
|
||||||
.node_data[clip_item.scroll_node_data_index.0 as usize];
|
.node_data[clip_item.scroll_node_data_index.0 as usize]
|
||||||
|
.transform;
|
||||||
let prim_transform = &prim_run_context.scroll_node.world_content_transform;
|
let prim_transform = &prim_run_context.scroll_node.world_content_transform;
|
||||||
|
|
||||||
let relative_transform = prim_transform
|
let relative_transform = prim_transform
|
||||||
.inverse()
|
.inverse()
|
||||||
.unwrap_or(WorldToLayerTransform::identity())
|
.unwrap_or(WorldToLayerFastTransform::identity())
|
||||||
.pre_mul(&clip_transform_data.transform);
|
.pre_mul(&clip_transform.into());
|
||||||
|
|
||||||
relative_transform.transform_rect(&local_clip_rect)
|
relative_transform.transform_rect(&local_clip_rect)
|
||||||
};
|
};
|
||||||
|
@ -2061,8 +2025,7 @@ fn get_local_clip_rect_for_nodes(
|
||||||
);
|
);
|
||||||
|
|
||||||
match local_rect {
|
match local_rect {
|
||||||
Some(local_rect) =>
|
Some(local_rect) => scroll_node.coordinate_system_relative_transform.unapply(&local_rect),
|
||||||
Some(scroll_node.coordinate_system_relative_transform.unapply(&local_rect)),
|
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1007,6 +1007,9 @@ impl RenderBackend {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let msg_update = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
|
||||||
|
self.result_tx.send(msg_update).unwrap();
|
||||||
|
|
||||||
let msg_publish = ResultMsg::PublishDocument(
|
let msg_publish = ResultMsg::PublishDocument(
|
||||||
id,
|
id,
|
||||||
render_doc,
|
render_doc,
|
||||||
|
|
|
@ -83,6 +83,10 @@ const GPU_CACHE_RESIZE_TEST: bool = false;
|
||||||
/// Number of GPU blocks per UV rectangle provided for an image.
|
/// Number of GPU blocks per UV rectangle provided for an image.
|
||||||
pub const BLOCKS_PER_UV_RECT: usize = 2;
|
pub const BLOCKS_PER_UV_RECT: usize = 2;
|
||||||
|
|
||||||
|
const GPU_TAG_BRUSH_LINEAR_GRADIENT: GpuProfileTag = GpuProfileTag {
|
||||||
|
label: "B_LinearGradient",
|
||||||
|
color: debug_colors::POWDERBLUE,
|
||||||
|
};
|
||||||
const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
|
const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
|
||||||
label: "B_RadialGradient",
|
label: "B_RadialGradient",
|
||||||
color: debug_colors::LIGHTPINK,
|
color: debug_colors::LIGHTPINK,
|
||||||
|
@ -151,14 +155,6 @@ const GPU_TAG_PRIM_TEXT_RUN: GpuProfileTag = GpuProfileTag {
|
||||||
label: "TextRun",
|
label: "TextRun",
|
||||||
color: debug_colors::BLUE,
|
color: debug_colors::BLUE,
|
||||||
};
|
};
|
||||||
const GPU_TAG_PRIM_GRADIENT: GpuProfileTag = GpuProfileTag {
|
|
||||||
label: "Gradient",
|
|
||||||
color: debug_colors::YELLOW,
|
|
||||||
};
|
|
||||||
const GPU_TAG_PRIM_ANGLE_GRADIENT: GpuProfileTag = GpuProfileTag {
|
|
||||||
label: "AngleGradient",
|
|
||||||
color: debug_colors::POWDERBLUE,
|
|
||||||
};
|
|
||||||
const GPU_TAG_PRIM_BORDER_CORNER: GpuProfileTag = GpuProfileTag {
|
const GPU_TAG_PRIM_BORDER_CORNER: GpuProfileTag = GpuProfileTag {
|
||||||
label: "BorderCorner",
|
label: "BorderCorner",
|
||||||
color: debug_colors::DARKSLATEGREY,
|
color: debug_colors::DARKSLATEGREY,
|
||||||
|
@ -200,8 +196,6 @@ impl TransformBatchKind {
|
||||||
ImageBufferKind::TextureExternal => "Image (External)",
|
ImageBufferKind::TextureExternal => "Image (External)",
|
||||||
ImageBufferKind::Texture2DArray => "Image (Array)",
|
ImageBufferKind::Texture2DArray => "Image (Array)",
|
||||||
},
|
},
|
||||||
TransformBatchKind::AlignedGradient => "AlignedGradient",
|
|
||||||
TransformBatchKind::AngleGradient => "AngleGradient",
|
|
||||||
TransformBatchKind::BorderCorner => "BorderCorner",
|
TransformBatchKind::BorderCorner => "BorderCorner",
|
||||||
TransformBatchKind::BorderEdge => "BorderEdge",
|
TransformBatchKind::BorderEdge => "BorderEdge",
|
||||||
}
|
}
|
||||||
|
@ -213,8 +207,6 @@ impl TransformBatchKind {
|
||||||
TransformBatchKind::Image(..) => GPU_TAG_PRIM_IMAGE,
|
TransformBatchKind::Image(..) => GPU_TAG_PRIM_IMAGE,
|
||||||
TransformBatchKind::BorderCorner => GPU_TAG_PRIM_BORDER_CORNER,
|
TransformBatchKind::BorderCorner => GPU_TAG_PRIM_BORDER_CORNER,
|
||||||
TransformBatchKind::BorderEdge => GPU_TAG_PRIM_BORDER_EDGE,
|
TransformBatchKind::BorderEdge => GPU_TAG_PRIM_BORDER_EDGE,
|
||||||
TransformBatchKind::AlignedGradient => GPU_TAG_PRIM_GRADIENT,
|
|
||||||
TransformBatchKind::AngleGradient => GPU_TAG_PRIM_ANGLE_GRADIENT,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,6 +227,7 @@ impl BatchKind {
|
||||||
BrushBatchKind::MixBlend { .. } => "Brush (Composite)",
|
BrushBatchKind::MixBlend { .. } => "Brush (Composite)",
|
||||||
BrushBatchKind::YuvImage(..) => "Brush (YuvImage)",
|
BrushBatchKind::YuvImage(..) => "Brush (YuvImage)",
|
||||||
BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
|
BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
|
||||||
|
BrushBatchKind::LinearGradient => "Brush (LinearGradient)",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(),
|
BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(),
|
||||||
|
@ -255,6 +248,7 @@ impl BatchKind {
|
||||||
BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
|
BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
|
||||||
BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
|
BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
|
||||||
BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
|
BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
|
||||||
|
BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(),
|
BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(),
|
||||||
|
@ -1618,6 +1612,7 @@ pub struct Renderer {
|
||||||
brush_mix_blend: BrushShader,
|
brush_mix_blend: BrushShader,
|
||||||
brush_yuv_image: Vec<Option<BrushShader>>,
|
brush_yuv_image: Vec<Option<BrushShader>>,
|
||||||
brush_radial_gradient: BrushShader,
|
brush_radial_gradient: BrushShader,
|
||||||
|
brush_linear_gradient: BrushShader,
|
||||||
|
|
||||||
/// These are "cache clip shaders". These shaders are used to
|
/// These are "cache clip shaders". These shaders are used to
|
||||||
/// draw clip instances into the cached clip mask. The results
|
/// draw clip instances into the cached clip mask. The results
|
||||||
|
@ -1638,8 +1633,6 @@ pub struct Renderer {
|
||||||
ps_image: Vec<Option<PrimitiveShader>>,
|
ps_image: Vec<Option<PrimitiveShader>>,
|
||||||
ps_border_corner: PrimitiveShader,
|
ps_border_corner: PrimitiveShader,
|
||||||
ps_border_edge: PrimitiveShader,
|
ps_border_edge: PrimitiveShader,
|
||||||
ps_gradient: PrimitiveShader,
|
|
||||||
ps_angle_gradient: PrimitiveShader,
|
|
||||||
|
|
||||||
ps_hw_composite: LazilyCompiledShader,
|
ps_hw_composite: LazilyCompiledShader,
|
||||||
ps_split_composite: LazilyCompiledShader,
|
ps_split_composite: LazilyCompiledShader,
|
||||||
|
@ -1884,6 +1877,17 @@ impl Renderer {
|
||||||
options.precache_shaders)
|
options.precache_shaders)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let brush_linear_gradient = try!{
|
||||||
|
BrushShader::new("brush_linear_gradient",
|
||||||
|
&mut device,
|
||||||
|
if options.enable_dithering {
|
||||||
|
&dithering_feature
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
},
|
||||||
|
options.precache_shaders)
|
||||||
|
};
|
||||||
|
|
||||||
let cs_blur_a8 = try!{
|
let cs_blur_a8 = try!{
|
||||||
LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur),
|
LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur),
|
||||||
"cs_blur",
|
"cs_blur",
|
||||||
|
@ -2030,28 +2034,6 @@ impl Renderer {
|
||||||
options.precache_shaders)
|
options.precache_shaders)
|
||||||
};
|
};
|
||||||
|
|
||||||
let ps_gradient = try!{
|
|
||||||
PrimitiveShader::new("ps_gradient",
|
|
||||||
&mut device,
|
|
||||||
if options.enable_dithering {
|
|
||||||
&dithering_feature
|
|
||||||
} else {
|
|
||||||
&[]
|
|
||||||
},
|
|
||||||
options.precache_shaders)
|
|
||||||
};
|
|
||||||
|
|
||||||
let ps_angle_gradient = try!{
|
|
||||||
PrimitiveShader::new("ps_angle_gradient",
|
|
||||||
&mut device,
|
|
||||||
if options.enable_dithering {
|
|
||||||
&dithering_feature
|
|
||||||
} else {
|
|
||||||
&[]
|
|
||||||
},
|
|
||||||
options.precache_shaders)
|
|
||||||
};
|
|
||||||
|
|
||||||
let ps_hw_composite = try!{
|
let ps_hw_composite = try!{
|
||||||
LazilyCompiledShader::new(ShaderKind::Primitive,
|
LazilyCompiledShader::new(ShaderKind::Primitive,
|
||||||
"ps_hardware_composite",
|
"ps_hardware_composite",
|
||||||
|
@ -2303,6 +2285,7 @@ impl Renderer {
|
||||||
brush_mix_blend,
|
brush_mix_blend,
|
||||||
brush_yuv_image,
|
brush_yuv_image,
|
||||||
brush_radial_gradient,
|
brush_radial_gradient,
|
||||||
|
brush_linear_gradient,
|
||||||
cs_clip_rectangle,
|
cs_clip_rectangle,
|
||||||
cs_clip_border,
|
cs_clip_border,
|
||||||
cs_clip_image,
|
cs_clip_image,
|
||||||
|
@ -2311,8 +2294,6 @@ impl Renderer {
|
||||||
ps_image,
|
ps_image,
|
||||||
ps_border_corner,
|
ps_border_corner,
|
||||||
ps_border_edge,
|
ps_border_edge,
|
||||||
ps_gradient,
|
|
||||||
ps_angle_gradient,
|
|
||||||
ps_hw_composite,
|
ps_hw_composite,
|
||||||
ps_split_composite,
|
ps_split_composite,
|
||||||
debug: debug_renderer,
|
debug: debug_renderer,
|
||||||
|
@ -2892,7 +2873,9 @@ impl Renderer {
|
||||||
for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents {
|
for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents {
|
||||||
frame.profile_counters.reset_targets();
|
frame.profile_counters.reset_targets();
|
||||||
self.prepare_gpu_cache(frame);
|
self.prepare_gpu_cache(frame);
|
||||||
assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id);
|
assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id,
|
||||||
|
"Received frame depends on a later GPU cache epoch ({:?}) than one we received last via `UpdateGpuCache` ({:?})",
|
||||||
|
frame.gpu_cache_frame_id, self.gpu_cache_frame_id);
|
||||||
|
|
||||||
self.draw_tile_frame(
|
self.draw_tile_frame(
|
||||||
frame,
|
frame,
|
||||||
|
@ -3272,6 +3255,15 @@ impl Renderer {
|
||||||
&mut self.renderer_errors,
|
&mut self.renderer_errors,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
BrushBatchKind::LinearGradient => {
|
||||||
|
self.brush_linear_gradient.bind(
|
||||||
|
&mut self.device,
|
||||||
|
key.blend_mode,
|
||||||
|
projection,
|
||||||
|
0,
|
||||||
|
&mut self.renderer_errors,
|
||||||
|
);
|
||||||
|
}
|
||||||
BrushBatchKind::YuvImage(image_buffer_kind, format, color_space) => {
|
BrushBatchKind::YuvImage(image_buffer_kind, format, color_space) => {
|
||||||
let shader_index =
|
let shader_index =
|
||||||
Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space);
|
Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space);
|
||||||
|
@ -3322,24 +3314,6 @@ impl Renderer {
|
||||||
&mut self.renderer_errors,
|
&mut self.renderer_errors,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
TransformBatchKind::AlignedGradient => {
|
|
||||||
self.ps_gradient.bind(
|
|
||||||
&mut self.device,
|
|
||||||
transform_kind,
|
|
||||||
projection,
|
|
||||||
0,
|
|
||||||
&mut self.renderer_errors,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
TransformBatchKind::AngleGradient => {
|
|
||||||
self.ps_angle_gradient.bind(
|
|
||||||
&mut self.device,
|
|
||||||
transform_kind,
|
|
||||||
projection,
|
|
||||||
0,
|
|
||||||
&mut self.renderer_errors,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4741,6 +4715,7 @@ impl Renderer {
|
||||||
self.brush_blend.deinit(&mut self.device);
|
self.brush_blend.deinit(&mut self.device);
|
||||||
self.brush_mix_blend.deinit(&mut self.device);
|
self.brush_mix_blend.deinit(&mut self.device);
|
||||||
self.brush_radial_gradient.deinit(&mut self.device);
|
self.brush_radial_gradient.deinit(&mut self.device);
|
||||||
|
self.brush_linear_gradient.deinit(&mut self.device);
|
||||||
self.cs_clip_rectangle.deinit(&mut self.device);
|
self.cs_clip_rectangle.deinit(&mut self.device);
|
||||||
self.cs_clip_image.deinit(&mut self.device);
|
self.cs_clip_image.deinit(&mut self.device);
|
||||||
self.cs_clip_border.deinit(&mut self.device);
|
self.cs_clip_border.deinit(&mut self.device);
|
||||||
|
@ -4766,8 +4741,6 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
self.ps_border_corner.deinit(&mut self.device);
|
self.ps_border_corner.deinit(&mut self.device);
|
||||||
self.ps_border_edge.deinit(&mut self.device);
|
self.ps_border_edge.deinit(&mut self.device);
|
||||||
self.ps_gradient.deinit(&mut self.device);
|
|
||||||
self.ps_angle_gradient.deinit(&mut self.device);
|
|
||||||
self.ps_hw_composite.deinit(&mut self.device);
|
self.ps_hw_composite.deinit(&mut self.device);
|
||||||
self.ps_split_composite.deinit(&mut self.device);
|
self.ps_split_composite.deinit(&mut self.device);
|
||||||
#[cfg(feature = "capture")]
|
#[cfg(feature = "capture")]
|
||||||
|
|
|
@ -16,7 +16,7 @@ use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex};
|
||||||
use gpu_types::{PrimitiveInstance};
|
use gpu_types::{PrimitiveInstance};
|
||||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||||
use picture::{PictureKind};
|
use picture::{PictureKind};
|
||||||
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveStore};
|
use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveKind, PrimitiveStore};
|
||||||
use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask};
|
use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask};
|
||||||
use profiler::FrameProfileCounters;
|
use profiler::FrameProfileCounters;
|
||||||
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
|
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
|
||||||
|
@ -46,6 +46,7 @@ pub struct RenderTargetContext<'a> {
|
||||||
pub clip_scroll_tree: &'a ClipScrollTree,
|
pub clip_scroll_tree: &'a ClipScrollTree,
|
||||||
pub use_dual_source_blending: bool,
|
pub use_dual_source_blending: bool,
|
||||||
pub node_data: &'a [ClipScrollNodeData],
|
pub node_data: &'a [ClipScrollNodeData],
|
||||||
|
pub cached_gradients: &'a [CachedGradient],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||||
|
@ -599,6 +600,7 @@ impl RenderTarget for AlphaRenderTarget {
|
||||||
BrushKind::Line { .. } |
|
BrushKind::Line { .. } |
|
||||||
BrushKind::YuvImage { .. } |
|
BrushKind::YuvImage { .. } |
|
||||||
BrushKind::RadialGradient { .. } |
|
BrushKind::RadialGradient { .. } |
|
||||||
|
BrushKind::LinearGradient { .. } |
|
||||||
BrushKind::Image { .. } => {
|
BrushKind::Image { .. } => {
|
||||||
unreachable!("bug: unexpected brush here");
|
unreachable!("bug: unexpected brush here");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
|
use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
|
||||||
use api::{DevicePoint, DeviceRect, DeviceSize, LayerPoint, LayerRect, LayerSize};
|
use api::{DevicePoint, DeviceRect, DeviceSize, LayerPixel, LayerPoint, LayerRect, LayerSize};
|
||||||
use api::{LayerToWorldTransform, LayerTransform, LayerVector2D, WorldRect};
|
use api::{LayoutPixel, WorldPixel, WorldRect};
|
||||||
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, TypedTransform2D};
|
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedPoint3D, TypedRect, TypedSize2D};
|
||||||
use euclid::TypedTransform3D;
|
use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D};
|
||||||
use num_traits::Zero;
|
use num_traits::Zero;
|
||||||
use std::{i32, f32};
|
use std::{i32, f32};
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ pub trait MatrixHelpers<Src, Dst> {
|
||||||
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src>;
|
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src>;
|
||||||
fn transform_kind(&self) -> TransformedRectKind;
|
fn transform_kind(&self) -> TransformedRectKind;
|
||||||
fn is_simple_translation(&self) -> bool;
|
fn is_simple_translation(&self) -> bool;
|
||||||
|
fn is_simple_2d_translation(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
||||||
|
@ -105,6 +106,14 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
||||||
self.m31.abs() < NEARLY_ZERO && self.m32.abs() < NEARLY_ZERO &&
|
self.m31.abs() < NEARLY_ZERO && self.m32.abs() < NEARLY_ZERO &&
|
||||||
self.m34.abs() < NEARLY_ZERO
|
self.m34.abs() < NEARLY_ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_simple_2d_translation(&self) -> bool {
|
||||||
|
if !self.is_simple_translation() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.m43.abs() < NEARLY_ZERO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RectHelpers<U>
|
pub trait RectHelpers<U>
|
||||||
|
@ -145,7 +154,7 @@ pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_screen_bounding_rect(
|
pub fn calculate_screen_bounding_rect(
|
||||||
transform: &LayerToWorldTransform,
|
transform: &LayerToWorldFastTransform,
|
||||||
rect: &LayerRect,
|
rect: &LayerRect,
|
||||||
device_pixel_scale: DevicePixelScale,
|
device_pixel_scale: DevicePixelScale,
|
||||||
) -> DeviceIntRect {
|
) -> DeviceIntRect {
|
||||||
|
@ -334,67 +343,189 @@ impl MaxRect for DeviceRect {
|
||||||
|
|
||||||
/// An enum that tries to avoid expensive transformation matrix calculations
|
/// An enum that tries to avoid expensive transformation matrix calculations
|
||||||
/// when possible when dealing with non-perspective axis-aligned transformations.
|
/// when possible when dealing with non-perspective axis-aligned transformations.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum TransformOrOffset {
|
pub enum FastTransform<Src, Dst> {
|
||||||
/// A simple offset, which can be used without doing any matrix math.
|
/// A simple offset, which can be used without doing any matrix math.
|
||||||
Offset(LayerVector2D),
|
Offset(TypedVector2D<f32, Src>),
|
||||||
|
|
||||||
/// A transformation with an inverse. If the inverse isn't present, this isn't a 2D
|
/// A 2D transformation with an inverse.
|
||||||
/// transformation, which means we need to fall back to using inverse_rect_footprint.
|
|
||||||
/// Since this operation is so expensive, we avoid it for the 2D case.
|
|
||||||
Transform {
|
Transform {
|
||||||
transform: LayerTransform,
|
transform: TypedTransform3D<f32, Src, Dst>,
|
||||||
inverse: Option<LayerTransform>,
|
inverse: Option<TypedTransform3D<f32, Dst, Src>>,
|
||||||
}
|
is_2d: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransformOrOffset {
|
impl<Src, Dst> FastTransform<Src, Dst> {
|
||||||
pub fn zero() -> TransformOrOffset {
|
pub fn identity() -> Self {
|
||||||
TransformOrOffset::Offset(LayerVector2D::zero())
|
FastTransform::Offset(TypedVector2D::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_transform(transform: LayerTransform) -> TransformOrOffset {
|
pub fn with_vector(offset: TypedVector2D<f32, Src>) -> Self {
|
||||||
if transform.is_2d() {
|
FastTransform::Offset(offset)
|
||||||
TransformOrOffset::Transform {
|
|
||||||
transform,
|
|
||||||
inverse: Some(transform.inverse().expect("Expected invertible matrix."))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TransformOrOffset::Transform { transform, inverse: None }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply(&self, rect: &LayerRect) -> LayerRect {
|
#[inline(always)]
|
||||||
|
pub fn with_transform(transform: TypedTransform3D<f32, Src, Dst>) -> Self {
|
||||||
|
if transform.is_simple_2d_translation() {
|
||||||
|
return FastTransform::Offset(TypedVector2D::new(transform.m41, transform.m42));
|
||||||
|
}
|
||||||
|
let inverse = transform.inverse();
|
||||||
|
let is_2d = transform.is_2d();
|
||||||
|
FastTransform::Transform { transform, inverse, is_2d}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_transform(&self) -> TypedTransform3D<f32, Src, Dst> {
|
||||||
match *self {
|
match *self {
|
||||||
TransformOrOffset::Offset(offset) => rect.translate(&offset),
|
FastTransform::Offset(offset) =>
|
||||||
TransformOrOffset::Transform {transform, .. } => transform.transform_rect(&rect),
|
TypedTransform3D::create_translation(offset.x, offset.y, 0.0),
|
||||||
|
FastTransform::Transform { transform, .. } => transform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unapply(&self, rect: &LayerRect) -> LayerRect {
|
pub fn is_invertible(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
TransformOrOffset::Offset(offset) => rect.translate(&-offset),
|
FastTransform::Offset(..) => true,
|
||||||
TransformOrOffset::Transform { inverse: Some(inverse), .. } =>
|
FastTransform::Transform { ref inverse, .. } => inverse.is_some(),
|
||||||
inverse.transform_rect(&rect),
|
|
||||||
TransformOrOffset::Transform { transform, inverse: None } =>
|
|
||||||
transform.inverse_rect_footprint(rect),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self, new_offset: LayerVector2D) -> TransformOrOffset {
|
#[inline(always)]
|
||||||
|
pub fn pre_mul<NewSrc>(
|
||||||
|
&self,
|
||||||
|
other: &FastTransform<NewSrc, Src>
|
||||||
|
) -> FastTransform<NewSrc, Dst> {
|
||||||
|
match (self, other) {
|
||||||
|
(&FastTransform::Offset(ref offset), &FastTransform::Offset(ref other_offset)) => {
|
||||||
|
let offset = TypedVector2D::from_untyped(&offset.to_untyped());
|
||||||
|
FastTransform::Offset((offset + *other_offset))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let new_transform = self.to_transform().pre_mul(&other.to_transform());
|
||||||
|
FastTransform::with_transform(new_transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn pre_translate(&self, other_offset: &TypedVector2D<f32, Src>) -> Self {
|
||||||
|
match self {
|
||||||
|
&FastTransform::Offset(ref offset) =>
|
||||||
|
return FastTransform::Offset(*offset + *other_offset),
|
||||||
|
&FastTransform::Transform { transform, .. } =>
|
||||||
|
FastTransform::with_transform(transform.pre_translate(other_offset.to_3d()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn preserves_2d_axis_alignment(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
TransformOrOffset::Offset(offset) => TransformOrOffset::Offset(offset + new_offset),
|
FastTransform::Offset(..) => true,
|
||||||
TransformOrOffset::Transform { transform, .. } => {
|
FastTransform::Transform { ref transform, .. } =>
|
||||||
|
transform.preserves_2d_axis_alignment(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn has_perspective_component(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(..) => false,
|
||||||
|
FastTransform::Transform { ref transform, .. } => transform.has_perspective_component(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_backface_visible(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(..) => false,
|
||||||
|
FastTransform::Transform { ref transform, .. } => transform.is_backface_visible(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn transform_point2d(&self, point: &TypedPoint2D<f32, Src>) -> TypedPoint2D<f32, Dst> {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(offset) => {
|
||||||
|
let new_point = *point + offset;
|
||||||
|
TypedPoint2D::from_untyped(&new_point.to_untyped())
|
||||||
|
}
|
||||||
|
FastTransform::Transform { ref transform, .. } => transform.transform_point2d(point),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn transform_point3d(&self, point: &TypedPoint3D<f32, Src>) -> TypedPoint3D<f32, Dst> {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(offset) =>
|
||||||
|
TypedPoint3D::new(point.x + offset.x, point.y + offset.y, point.z),
|
||||||
|
FastTransform::Transform { ref transform, .. } => transform.transform_point3d(point),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn transform_rect(&self, rect: &TypedRect<f32, Src>) -> TypedRect<f32, Dst> {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(offset) =>
|
||||||
|
TypedRect::from_untyped(&rect.to_untyped().translate(&offset.to_untyped())),
|
||||||
|
FastTransform::Transform { ref transform, .. } => transform.transform_rect(rect),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unapply(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>> {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(offset) =>
|
||||||
|
Some(TypedRect::from_untyped(&rect.to_untyped().translate(&-offset.to_untyped()))),
|
||||||
|
FastTransform::Transform { inverse: Some(ref inverse), is_2d: true, .. } =>
|
||||||
|
Some(inverse.transform_rect(&rect)),
|
||||||
|
FastTransform::Transform { ref transform, is_2d: false, .. } =>
|
||||||
|
Some(transform.inverse_rect_footprint(rect)),
|
||||||
|
FastTransform::Transform { inverse: None, .. } => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn offset(&self, new_offset: TypedVector2D<f32, Src>) -> Self {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(offset) => FastTransform::Offset(offset + new_offset),
|
||||||
|
FastTransform::Transform { ref transform, .. } => {
|
||||||
let transform = transform.pre_translate(new_offset.to_3d());
|
let transform = transform.pre_translate(new_offset.to_3d());
|
||||||
TransformOrOffset::new_transform(transform)
|
FastTransform::with_transform(transform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, transform: LayerTransform) -> Option<TransformOrOffset> {
|
pub fn post_translate(&self, new_offset: TypedVector2D<f32, Dst>) -> Self {
|
||||||
if transform.is_simple_translation() {
|
match *self {
|
||||||
let offset = LayerVector2D::new(transform.m41, transform.m42);
|
FastTransform::Offset(offset) => {
|
||||||
Some(self.offset(offset))
|
let offset = offset.to_untyped() + new_offset.to_untyped();
|
||||||
|
FastTransform::Offset(TypedVector2D::from_untyped(&offset))
|
||||||
|
}
|
||||||
|
FastTransform::Transform { ref transform, .. } => {
|
||||||
|
let transform = transform.post_translate(new_offset.to_3d());
|
||||||
|
FastTransform::with_transform(transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn inverse(&self) -> Option<FastTransform<Dst, Src>> {
|
||||||
|
match *self {
|
||||||
|
FastTransform::Offset(offset) =>
|
||||||
|
Some(FastTransform::Offset(TypedVector2D::new(-offset.x, -offset.y))),
|
||||||
|
FastTransform::Transform { transform, inverse: Some(inverse), is_2d, } =>
|
||||||
|
Some(FastTransform::Transform {
|
||||||
|
transform: inverse,
|
||||||
|
inverse: Some(transform),
|
||||||
|
is_2d
|
||||||
|
}),
|
||||||
|
FastTransform::Transform { inverse: None, .. } => None,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&self, transform: TypedTransform3D<f32, Src, Dst>) -> Option<Self> {
|
||||||
|
if transform.is_simple_2d_translation() {
|
||||||
|
Some(self.offset(TypedVector2D::new(transform.m41, transform.m42)))
|
||||||
} else {
|
} else {
|
||||||
// If we break 2D axis alignment or have a perspective component, we need to start a
|
// If we break 2D axis alignment or have a perspective component, we need to start a
|
||||||
// new incompatible coordinate system with which we cannot share clips without masking.
|
// new incompatible coordinate system with which we cannot share clips without masking.
|
||||||
|
@ -402,3 +533,26 @@ impl TransformOrOffset {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
|
||||||
|
fn from(transform: TypedTransform3D<f32, Src, Dst>) -> FastTransform<Src, Dst> {
|
||||||
|
FastTransform::with_transform(transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Src, Dst> Into<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
|
||||||
|
fn into(self) -> TypedTransform3D<f32, Src, Dst> {
|
||||||
|
self.to_transform()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
|
||||||
|
fn from(vector: TypedVector2D<f32, Src>) -> 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>;
|
||||||
|
|
|
@ -54,14 +54,6 @@ const SHADERS: &[Shader] = &[
|
||||||
name: "ps_border_edge",
|
name: "ps_border_edge",
|
||||||
features: PRIM_FEATURES,
|
features: PRIM_FEATURES,
|
||||||
},
|
},
|
||||||
Shader {
|
|
||||||
name: "ps_gradient",
|
|
||||||
features: PRIM_FEATURES,
|
|
||||||
},
|
|
||||||
Shader {
|
|
||||||
name: "ps_angle_gradient",
|
|
||||||
features: PRIM_FEATURES,
|
|
||||||
},
|
|
||||||
Shader {
|
Shader {
|
||||||
name: "ps_hardware_composite",
|
name: "ps_hardware_composite",
|
||||||
features: PRIM_FEATURES,
|
features: PRIM_FEATURES,
|
||||||
|
@ -81,7 +73,7 @@ const SHADERS: &[Shader] = &[
|
||||||
// Brush shaders
|
// Brush shaders
|
||||||
Shader {
|
Shader {
|
||||||
name: "brush_yuv_image",
|
name: "brush_yuv_image",
|
||||||
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED"],
|
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED", "YUV_NV12,TEXTURE_RECT"],
|
||||||
},
|
},
|
||||||
Shader {
|
Shader {
|
||||||
name: "brush_mask",
|
name: "brush_mask",
|
||||||
|
@ -109,6 +101,10 @@ const SHADERS: &[Shader] = &[
|
||||||
},
|
},
|
||||||
Shader {
|
Shader {
|
||||||
name: "brush_radial_gradient",
|
name: "brush_radial_gradient",
|
||||||
|
features: &[ "DITHERING" ],
|
||||||
|
},
|
||||||
|
Shader {
|
||||||
|
name: "brush_linear_gradient",
|
||||||
features: &[],
|
features: &[],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
e8d2ffb404a85651fe08a6d09abbece9bd2b9182
|
8a19316a733a484bf9bafb8257e3008b1418bfe4
|
||||||
|
|
Загрузка…
Ссылка в новой задаче