зеркало из 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
|
||||
* 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
|
||||
|
||||
#include shared,prim_shared,brush
|
||||
|
@ -83,9 +83,10 @@ void brush_vs(
|
|||
}
|
||||
case 10: {
|
||||
// Color Matrix
|
||||
vec4 data[4] = fetch_from_resource_cache_4(prim_address + 1);
|
||||
vColorMat = mat4(amount, data[0], data[1], data[2]);
|
||||
vColorOffset = data[3];
|
||||
vec4 mat_data[4] = fetch_from_resource_cache_4(user_data.z);
|
||||
vec4 offset_data = fetch_from_resource_cache_1(user_data.z + 4);
|
||||
vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]);
|
||||
vColorOffset = offset_data;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
|
|
@ -40,7 +40,12 @@ void brush_vs(
|
|||
vUv.xy = mix(uv0, uv1, f);
|
||||
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
|
||||
vLocalPos = vi.local_pos;
|
||||
|
|
|
@ -119,38 +119,7 @@ void brush_vs(
|
|||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
#define MAGIC_WAVY_LINE_AA_SNAP 0.7
|
||||
|
||||
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));
|
||||
}
|
||||
#define MAGIC_WAVY_LINE_AA_SNAP 0.5
|
||||
|
||||
vec4 brush_fs() {
|
||||
// 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
|
||||
* 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
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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 5
|
||||
#define VECS_PER_SPECIFIC_BRUSH 1
|
||||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ varying vec2 vLocalPos;
|
|||
flat varying vec4 vUvBounds_YUV;
|
||||
#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
|
||||
void write_uv_rect(
|
||||
int resource_id,
|
||||
|
@ -78,14 +84,14 @@ void brush_vs(
|
|||
#endif
|
||||
|
||||
#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.y, f, vec2(textureSize(sColor1, 0).xy), 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.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
|
||||
write_uv_rect(user_data.z, f, TEX_SIZE(sColor2), vUv_V, vUvBounds_V);
|
||||
#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.y, f, vec2(textureSize(sColor1, 0).xy), vUv_UV, vUvBounds_UV);
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_UV, vUvBounds_UV);
|
||||
#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
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define SUBPX_DIR_HORIZONTAL 1
|
||||
#define SUBPX_DIR_VERTICAL 2
|
||||
|
||||
#define EPSILON 0.0001
|
||||
|
||||
uniform sampler2DArray sCacheA8;
|
||||
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_PRIM_HEADER 2
|
||||
#define VECS_PER_TEXT_RUN 3
|
||||
#define VECS_PER_GRADIENT 3
|
||||
#define VECS_PER_GRADIENT_STOP 2
|
||||
|
||||
uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes;
|
||||
|
@ -304,17 +305,6 @@ ClipArea fetch_clip_area(int index) {
|
|||
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 {
|
||||
vec2 offset;
|
||||
};
|
||||
|
@ -748,7 +738,7 @@ void write_clip(vec2 global_pos, ClipArea area) {
|
|||
|
||||
#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.
|
||||
float compute_aa_range(vec2 position) {
|
||||
// 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
|
||||
// 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.
|
||||
// It gives a smoother (although blurrier look) by extending the range that is smoothed
|
||||
// to produce the anti aliasing. In our case, however, extending the range inside of
|
||||
// the shape causes noticeable artifacts at the junction between an antialiased corner
|
||||
// and a straight edge.
|
||||
// Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
|
||||
// indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
|
||||
// a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
|
||||
// aliased corner and a straight edge.
|
||||
//
|
||||
// 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
|
||||
// when axis aligned, while selecting a larger and smoother aa range on curves).
|
||||
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.
|
||||
///
|
||||
/// 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) {
|
||||
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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
// 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)
|
||||
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
|
||||
#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)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveIn
|
|||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
||||
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 render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
|
||||
use renderer::{BlendMode, ImageBufferKind};
|
||||
|
@ -38,8 +38,6 @@ const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fff);
|
|||
pub enum TransformBatchKind {
|
||||
TextRun(GlyphFormat),
|
||||
Image(ImageBufferKind),
|
||||
AlignedGradient,
|
||||
AngleGradient,
|
||||
BorderCorner,
|
||||
BorderEdge,
|
||||
}
|
||||
|
@ -78,6 +76,7 @@ pub enum BrushBatchKind {
|
|||
},
|
||||
YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace),
|
||||
RadialGradient,
|
||||
LinearGradient,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
|
@ -682,6 +681,7 @@ impl AlphaBatchBuilder {
|
|||
ctx.resource_cache,
|
||||
gpu_cache,
|
||||
deferred_resolves,
|
||||
&ctx.cached_gradients,
|
||||
) {
|
||||
self.add_brush_to_batch(
|
||||
brush,
|
||||
|
@ -811,7 +811,7 @@ impl AlphaBatchBuilder {
|
|||
let font_transform = if is_shadow {
|
||||
None
|
||||
} else {
|
||||
Some(&scroll_node.transform)
|
||||
Some(scroll_node.transform)
|
||||
};
|
||||
|
||||
let font = text_cpu.get_font(
|
||||
|
@ -969,6 +969,7 @@ impl AlphaBatchBuilder {
|
|||
is_in_3d_context,
|
||||
reference_frame_id,
|
||||
real_local_rect,
|
||||
ref extra_gpu_data_handle,
|
||||
..
|
||||
} => {
|
||||
// If this picture is participating in a 3D rendering context,
|
||||
|
@ -977,8 +978,10 @@ impl AlphaBatchBuilder {
|
|||
if is_in_3d_context {
|
||||
// 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(
|
||||
real_local_rect,
|
||||
&real_xf,
|
||||
|
@ -1093,18 +1096,20 @@ impl AlphaBatchBuilder {
|
|||
BatchTextures::render_target_cache(),
|
||||
);
|
||||
|
||||
let filter_mode = match filter {
|
||||
FilterOp::Blur(..) => 0,
|
||||
FilterOp::Contrast(..) => 1,
|
||||
FilterOp::Grayscale(..) => 2,
|
||||
FilterOp::HueRotate(..) => 3,
|
||||
FilterOp::Invert(..) => 4,
|
||||
FilterOp::Saturate(..) => 5,
|
||||
FilterOp::Sepia(..) => 6,
|
||||
FilterOp::Brightness(..) => 7,
|
||||
FilterOp::Opacity(..) => 8,
|
||||
FilterOp::DropShadow(..) => 9,
|
||||
FilterOp::ColorMatrix(..) => 10,
|
||||
let (filter_mode, extra_cache_address) = match filter {
|
||||
FilterOp::Blur(..) => (0, 0),
|
||||
FilterOp::Contrast(..) => (1, 0),
|
||||
FilterOp::Grayscale(..) => (2, 0),
|
||||
FilterOp::HueRotate(..) => (3, 0),
|
||||
FilterOp::Invert(..) => (4, 0),
|
||||
FilterOp::Saturate(..) => (5, 0),
|
||||
FilterOp::Sepia(..) => (6, 0),
|
||||
FilterOp::Brightness(..) => (7, 0),
|
||||
FilterOp::Opacity(..) => (8, 0),
|
||||
FilterOp::DropShadow(..) => (9, 0),
|
||||
FilterOp::ColorMatrix(..) => {
|
||||
(10, extra_gpu_data_handle.as_int(gpu_cache))
|
||||
}
|
||||
};
|
||||
|
||||
let instance = BrushInstance {
|
||||
|
@ -1120,7 +1125,7 @@ impl AlphaBatchBuilder {
|
|||
user_data: [
|
||||
cache_task_address.0 as i32,
|
||||
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,
|
||||
gpu_cache: &mut GpuCache,
|
||||
deferred_resolves: &mut Vec<DeferredResolve>,
|
||||
cached_gradients: &[CachedGradient],
|
||||
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {
|
||||
match self.kind {
|
||||
BrushKind::Line { .. } => {
|
||||
|
@ -1376,7 +1360,8 @@ impl BrushPrimitive {
|
|||
[0; 3],
|
||||
))
|
||||
}
|
||||
BrushKind::RadialGradient { ref stops_handle, .. } => {
|
||||
BrushKind::RadialGradient { gradient_index, .. } => {
|
||||
let stops_handle = &cached_gradients[gradient_index.0].handle;
|
||||
Some((
|
||||
BrushBatchKind::RadialGradient,
|
||||
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 } => {
|
||||
let mut textures = BatchTextures::no_texture();
|
||||
let mut uv_rect_addresses = [0; 3];
|
||||
|
@ -1464,8 +1461,6 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
}
|
||||
|
||||
PrimitiveKind::Border |
|
||||
PrimitiveKind::AlignedGradient |
|
||||
PrimitiveKind::AngleGradient |
|
||||
PrimitiveKind::Picture => {
|
||||
BlendMode::PremultipliedAlpha
|
||||
}
|
||||
|
@ -1487,6 +1482,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
BrushKind::Line { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::LinearGradient { .. } |
|
||||
BrushKind::Picture => {
|
||||
BlendMode::PremultipliedAlpha
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
|
||||
use api::{ImageRendering, LayerRect, LayerToWorldTransform, LayoutPoint, LayoutVector2D};
|
||||
use api::LocalClip;
|
||||
use api::{ImageRendering, LayerRect, LayoutPoint, LayoutVector2D, LocalClip};
|
||||
use border::{BorderCornerClipSource, ensure_no_corner_overlap};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||
use ellipse::Ellipse;
|
||||
|
@ -13,7 +12,8 @@ use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
|
|||
use gpu_types::ClipScrollNodeIndex;
|
||||
use prim_store::{ClipData, ImageMaskData};
|
||||
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;
|
||||
|
||||
pub type ClipStore = FreeList<ClipSources>;
|
||||
|
@ -252,7 +252,7 @@ impl ClipSources {
|
|||
|
||||
pub fn get_screen_bounds(
|
||||
&self,
|
||||
transform: &LayerToWorldTransform,
|
||||
transform: &LayerToWorldFastTransform,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> (DeviceIntRect, Option<DeviceIntRect>) {
|
||||
// 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/. */
|
||||
|
||||
use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect};
|
||||
use api::{LayerSize, LayerToWorldTransform, LayerTransform, LayerVector2D, LayoutTransform};
|
||||
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollEventPhase};
|
||||
use api::{ScrollLocation, ScrollSensitivity, StickyOffsetBounds, WorldPoint};
|
||||
use api::{LayerSize, LayerVector2D, LayoutTransform, LayoutVector2D, PipelineId, PropertyBinding};
|
||||
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyOffsetBounds};
|
||||
use api::WorldPoint;
|
||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState};
|
||||
use euclid::SideOffsets2D;
|
||||
|
@ -15,7 +15,8 @@ use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData};
|
|||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use spring::{DAMPING, STIFFNESS, Spring};
|
||||
use util::{MatrixHelpers, TransformOrOffset, TransformedRectKind};
|
||||
use util::{LayerToWorldFastTransform, LayerFastTransform, LayoutFastTransform};
|
||||
use util::{TransformedRectKind};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
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
|
||||
/// whatever local transformation this reference frame provides. This can be combined
|
||||
/// with the local_viewport_rect to get its position in world space.
|
||||
pub world_viewport_transform: LayerToWorldTransform,
|
||||
pub world_viewport_transform: LayerToWorldFastTransform,
|
||||
|
||||
/// World transform for content transformed by this node.
|
||||
pub world_content_transform: LayerToWorldTransform,
|
||||
pub world_content_transform: LayerToWorldFastTransform,
|
||||
|
||||
/// Pipeline that this layer belongs to
|
||||
pub pipeline_id: PipelineId,
|
||||
|
@ -119,7 +120,7 @@ pub struct ClipScrollNode {
|
|||
/// The transformation from the coordinate system which established our compatible coordinate
|
||||
/// system (same coordinate system id) and us. This can change via scroll offsets and via new
|
||||
/// reference frame transforms.
|
||||
pub coordinate_system_relative_transform: TransformOrOffset,
|
||||
pub coordinate_system_relative_transform: LayerFastTransform,
|
||||
|
||||
/// 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.
|
||||
|
@ -135,15 +136,15 @@ impl ClipScrollNode {
|
|||
) -> Self {
|
||||
ClipScrollNode {
|
||||
local_viewport_rect: *rect,
|
||||
world_viewport_transform: LayerToWorldTransform::identity(),
|
||||
world_content_transform: LayerToWorldTransform::identity(),
|
||||
world_viewport_transform: LayerToWorldFastTransform::identity(),
|
||||
world_content_transform: LayerToWorldFastTransform::identity(),
|
||||
parent: parent_id,
|
||||
children: Vec::new(),
|
||||
pipeline_id,
|
||||
node_type: node_type,
|
||||
invertible: true,
|
||||
coordinate_system_id: CoordinateSystemId(0),
|
||||
coordinate_system_relative_transform: TransformOrOffset::zero(),
|
||||
coordinate_system_relative_transform: LayerFastTransform::identity(),
|
||||
node_data_index: ClipScrollNodeIndex(0),
|
||||
}
|
||||
}
|
||||
|
@ -177,10 +178,12 @@ impl ClipScrollNode {
|
|||
pipeline_id: PipelineId,
|
||||
) -> Self {
|
||||
let identity = LayoutTransform::identity();
|
||||
let source_perspective = source_perspective.map_or_else(
|
||||
LayoutFastTransform::identity, |perspective| perspective.into());
|
||||
let info = ReferenceFrameInfo {
|
||||
resolved_transform: LayerTransform::identity(),
|
||||
resolved_transform: LayerFastTransform::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,
|
||||
invertible: true,
|
||||
};
|
||||
|
@ -258,8 +261,8 @@ impl ClipScrollNode {
|
|||
|
||||
pub fn mark_uninvertible(&mut self) {
|
||||
self.invertible = false;
|
||||
self.world_content_transform = LayerToWorldTransform::identity();
|
||||
self.world_viewport_transform = LayerToWorldTransform::identity();
|
||||
self.world_content_transform = LayerToWorldFastTransform::identity();
|
||||
self.world_viewport_transform = LayerToWorldFastTransform::identity();
|
||||
}
|
||||
|
||||
pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) {
|
||||
|
@ -274,7 +277,7 @@ impl ClipScrollNode {
|
|||
TransformedRectKind::Complex
|
||||
};
|
||||
let data = ClipScrollNodeData {
|
||||
transform: self.world_content_transform,
|
||||
transform: self.world_content_transform.into(),
|
||||
transform_kind: transform_kind as u32 as f32,
|
||||
padding: [0.0; 3],
|
||||
};
|
||||
|
@ -303,9 +306,9 @@ impl ClipScrollNode {
|
|||
|
||||
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
|
||||
// has a non-invertible matrix. For non-reference-frames we assume that they will
|
||||
// produce only additional translations which should be invertible.
|
||||
// If this node is a reference frame, we check if it has a non-invertible matrix.
|
||||
// For non-reference-frames we assume that they will produce only additional
|
||||
// translations which should be invertible.
|
||||
match self.node_type {
|
||||
NodeType::ReferenceFrame(info) if !info.invertible => {
|
||||
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(
|
||||
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_inner_rect,
|
||||
);
|
||||
|
@ -398,7 +401,7 @@ impl ClipScrollNode {
|
|||
// provided by our own sticky positioning.
|
||||
let accumulated_offset = state.parent_accumulated_scroll_offset + sticky_offset;
|
||||
self.world_viewport_transform = if accumulated_offset != LayerVector2D::zero() {
|
||||
state.parent_reference_frame_transform.pre_translate(accumulated_offset.to_3d())
|
||||
state.parent_reference_frame_transform.pre_translate(&accumulated_offset)
|
||||
} else {
|
||||
state.parent_reference_frame_transform
|
||||
};
|
||||
|
@ -407,7 +410,7 @@ impl ClipScrollNode {
|
|||
// whatever scrolling offset we supply as well.
|
||||
let scroll_offset = self.scroll_offset();
|
||||
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 {
|
||||
self.world_viewport_transform
|
||||
};
|
||||
|
@ -437,12 +440,10 @@ impl ClipScrollNode {
|
|||
|
||||
// Resolve the transform against any property bindings.
|
||||
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
|
||||
info.resolved_transform = LayerTransform::create_translation(
|
||||
info.origin_in_parent_reference_frame.x,
|
||||
info.origin_in_parent_reference_frame.y,
|
||||
0.0
|
||||
).pre_mul(&source_transform)
|
||||
.pre_mul(&info.source_perspective);
|
||||
info.resolved_transform =
|
||||
LayerFastTransform::with_vector(info.origin_in_parent_reference_frame)
|
||||
.pre_mul(&source_transform.into())
|
||||
.pre_mul(&info.source_perspective);
|
||||
|
||||
// The transformation for this viewport in world coordinates is the transformation for
|
||||
// our parent reference frame, plus any accumulated scrolling offsets from nodes
|
||||
|
@ -450,12 +451,14 @@ impl ClipScrollNode {
|
|||
// whatever local transformation this reference frame provides. This can be combined
|
||||
// with the local_viewport_rect to get its position in world space.
|
||||
let relative_transform = info.resolved_transform
|
||||
.post_translate(state.parent_accumulated_scroll_offset.to_3d());
|
||||
self.world_viewport_transform = state.parent_reference_frame_transform
|
||||
.pre_mul(&relative_transform.with_destination::<LayerPixel>());
|
||||
.post_translate(state.parent_accumulated_scroll_offset)
|
||||
.to_transform()
|
||||
.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;
|
||||
|
||||
info.invertible = relative_transform.determinant() != 0.0;
|
||||
info.invertible = self.world_viewport_transform.is_invertible();
|
||||
if !info.invertible {
|
||||
return;
|
||||
}
|
||||
|
@ -465,7 +468,7 @@ impl ClipScrollNode {
|
|||
match state.coordinate_system_relative_transform.update(relative_transform) {
|
||||
Some(offset) => self.coordinate_system_relative_transform = offset,
|
||||
None => {
|
||||
self.coordinate_system_relative_transform = TransformOrOffset::zero();
|
||||
self.coordinate_system_relative_transform = LayerFastTransform::identity();
|
||||
state.current_coordinate_system_id = *next_coordinate_system_id;
|
||||
next_coordinate_system_id.advance();
|
||||
}
|
||||
|
@ -844,14 +847,14 @@ impl ScrollFrameInfo {
|
|||
pub struct ReferenceFrameInfo {
|
||||
/// The transformation that establishes this reference frame, relative to the parent
|
||||
/// reference frame. The origin of the reference frame is included in the transformation.
|
||||
pub resolved_transform: LayerTransform,
|
||||
pub resolved_transform: LayerFastTransform,
|
||||
|
||||
/// The source transform and perspective matrices provided by the stacking context
|
||||
/// that forms this reference frame. We maintain the property binding information
|
||||
/// here so that we can resolve the animated transform and update the tree each
|
||||
/// frame.
|
||||
pub source_transform: PropertyBinding<LayoutTransform>,
|
||||
pub source_perspective: LayoutTransform,
|
||||
pub source_perspective: LayoutFastTransform,
|
||||
|
||||
/// The original, not including the transform and relative to the parent reference frame,
|
||||
/// origin of this reference frame. This is already rolled into the `transform' property, but
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect};
|
||||
use api::{LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase};
|
||||
use api::{ScrollLocation, ScrollNodeState, WorldPoint};
|
||||
use api::{LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLocation};
|
||||
use api::{ScrollNodeState, WorldPoint};
|
||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore};
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo};
|
||||
use gpu_cache::GpuCache;
|
||||
|
@ -13,7 +13,7 @@ use internal_types::{FastHashMap, FastHashSet};
|
|||
use print_tree::{PrintTree, PrintTreePrinter};
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use util::TransformOrOffset;
|
||||
use util::{LayerFastTransform, LayerToWorldFastTransform};
|
||||
|
||||
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
|
||||
|
||||
|
@ -88,7 +88,7 @@ pub struct ClipScrollTree {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct TransformUpdateState {
|
||||
pub parent_reference_frame_transform: LayerToWorldTransform,
|
||||
pub parent_reference_frame_transform: LayerToWorldFastTransform,
|
||||
pub parent_accumulated_scroll_offset: LayerVector2D,
|
||||
pub nearest_scrolling_ancestor_offset: LayerVector2D,
|
||||
pub nearest_scrolling_ancestor_viewport: LayerRect,
|
||||
|
@ -103,7 +103,7 @@ pub struct TransformUpdateState {
|
|||
pub current_coordinate_system_id: CoordinateSystemId,
|
||||
|
||||
/// 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
|
||||
/// 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 mut state = TransformUpdateState {
|
||||
parent_reference_frame_transform: LayerToWorldTransform::create_translation(
|
||||
pan.x,
|
||||
pan.y,
|
||||
0.0,
|
||||
),
|
||||
parent_reference_frame_transform: LayerVector2D::new(pan.x, pan.y).into(),
|
||||
parent_accumulated_scroll_offset: LayerVector2D::zero(),
|
||||
nearest_scrolling_ancestor_offset: LayerVector2D::zero(),
|
||||
nearest_scrolling_ancestor_viewport: LayerRect::zero(),
|
||||
parent_clip_chain_index: ClipChainIndex(0),
|
||||
current_coordinate_system_id: CoordinateSystemId::root(),
|
||||
coordinate_system_relative_transform: TransformOrOffset::zero(),
|
||||
coordinate_system_relative_transform: LayerFastTransform::identity(),
|
||||
invertible: true,
|
||||
};
|
||||
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::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId};
|
||||
use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering};
|
||||
use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerTransform};
|
||||
use api::{LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip};
|
||||
use api::{PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow};
|
||||
use api::{TexelRect, TileOffset, TransformStyle, WorldPoint, WorldToLayerTransform, YuvColorSpace};
|
||||
use api::YuvData;
|
||||
use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D};
|
||||
use api::{LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip, PipelineId};
|
||||
use api::{PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow, TexelRect};
|
||||
use api::{TileOffset, TransformStyle, WorldPoint, YuvColorSpace, YuvData};
|
||||
use app_units::Au;
|
||||
use border::ImageBorderSegment;
|
||||
use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore};
|
||||
|
@ -19,12 +18,12 @@ use clip_scroll_tree::{ClipScrollTree, ClipChainIndex};
|
|||
use euclid::{SideOffsets2D, vec2};
|
||||
use frame::{FrameId, ClipIdToIndexMapper};
|
||||
use glyph_rasterizer::FontInstance;
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
|
||||
use hit_test::{HitTester, HitTestingItem, HitTestingRun};
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
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::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore};
|
||||
use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
|
||||
|
@ -35,7 +34,7 @@ use scene::{ScenePipeline, SceneProperties};
|
|||
use std::{mem, usize, f32};
|
||||
use tiling::{CompositeOps, Frame, RenderPass, RenderTargetKind};
|
||||
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)]
|
||||
pub struct ScrollbarInfo(pub ClipId, pub LayerRect);
|
||||
|
@ -86,6 +85,7 @@ pub struct FrameBuilder {
|
|||
pub clip_store: ClipStore,
|
||||
hit_testing_runs: Vec<HitTestingRun>,
|
||||
pub config: FrameBuilderConfig,
|
||||
pub cached_gradients: Vec<CachedGradient>,
|
||||
|
||||
// A stack of the current shadow primitives.
|
||||
// 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 resource_cache: &'a mut ResourceCache,
|
||||
pub gpu_cache: &'a mut GpuCache,
|
||||
pub cached_gradients: &'a mut [CachedGradient],
|
||||
}
|
||||
|
||||
pub struct PictureContext<'a> {
|
||||
|
@ -133,7 +134,7 @@ pub struct PictureContext<'a> {
|
|||
pub original_reference_frame_id: Option<ClipId>,
|
||||
pub display_list: &'a BuiltDisplayList,
|
||||
pub draw_text_transformed: bool,
|
||||
pub inv_world_transform: Option<WorldToLayerTransform>,
|
||||
pub inv_world_transform: Option<WorldToLayerFastTransform>,
|
||||
}
|
||||
|
||||
pub struct PictureState {
|
||||
|
@ -173,6 +174,7 @@ impl FrameBuilder {
|
|||
FrameBuilder {
|
||||
hit_testing_runs: Vec::new(),
|
||||
shadow_prim_stack: Vec::new(),
|
||||
cached_gradients: Vec::new(),
|
||||
pending_shadow_contents: Vec::new(),
|
||||
scrollbar_prims: Vec::new(),
|
||||
reference_frame_stack: Vec::new(),
|
||||
|
@ -201,6 +203,7 @@ impl FrameBuilder {
|
|||
FrameBuilder {
|
||||
hit_testing_runs: recycle_vec(self.hit_testing_runs),
|
||||
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),
|
||||
scrollbar_prims: recycle_vec(self.scrollbar_prims),
|
||||
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();
|
||||
if let Some(root_node) = clip_scroll_tree.nodes.get_mut(&root_id) {
|
||||
if let NodeType::ReferenceFrame(ref mut info) = root_node.node_type {
|
||||
info.resolved_transform = LayerTransform::create_translation(
|
||||
viewport_offset.x,
|
||||
viewport_offset.y,
|
||||
0.0,
|
||||
);
|
||||
info.resolved_transform =
|
||||
LayerVector2D::new(viewport_offset.x, viewport_offset.y).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
&mut self,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
|
@ -1248,62 +1295,40 @@ impl FrameBuilder {
|
|||
tile_size: LayerSize,
|
||||
tile_spacing: LayerSize,
|
||||
) {
|
||||
let tile_repeat = tile_size + tile_spacing;
|
||||
let is_not_tiled = tile_repeat.width >= info.rect.size.width &&
|
||||
tile_repeat.height >= info.rect.size.height;
|
||||
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||
self.cached_gradients.push(CachedGradient::new());
|
||||
|
||||
let aligned_and_fills_rect = (start_point.x == end_point.x &&
|
||||
start_point.y.min(end_point.y) <= 0.0 &&
|
||||
start_point.y.max(end_point.y) >= info.rect.size.height) ||
|
||||
(start_point.y == end_point.y && start_point.x.min(end_point.x) <= 0.0 &&
|
||||
start_point.x.max(end_point.x) >= info.rect.size.width);
|
||||
let prim_infos = info.decompose(
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
|
||||
// Fast path for clamped, axis-aligned gradients, with gradient lines intersecting all of rect:
|
||||
let aligned = extend_mode == ExtendMode::Clamp && is_not_tiled && aligned_and_fills_rect;
|
||||
|
||||
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
|
||||
// are also supplied in reverse that the rendered result will be equivalent. To do this,
|
||||
// a reference orientation for the gradient line must be chosen, somewhat arbitrarily, so
|
||||
// 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 = !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)
|
||||
if prim_infos.is_empty() {
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
);
|
||||
} else {
|
||||
(start_point, end_point)
|
||||
};
|
||||
|
||||
let gradient_cpu = GradientPrimitiveCpu {
|
||||
stops_range: stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
reverse_stops,
|
||||
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 {
|
||||
PrimitiveContainer::AngleGradient(gradient_cpu)
|
||||
};
|
||||
|
||||
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
|
||||
for prim_info in prim_infos {
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_radial_gradient_impl(
|
||||
|
@ -1317,17 +1342,18 @@ impl FrameBuilder {
|
|||
ratio_xy: f32,
|
||||
stops: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
gradient_index: CachedGradientIndex,
|
||||
) {
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::RadialGradient {
|
||||
stops_range: stops,
|
||||
extend_mode,
|
||||
stops_handle: GpuCacheHandle::new(),
|
||||
start_center,
|
||||
end_center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
gradient_index,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
@ -1354,6 +1380,9 @@ impl FrameBuilder {
|
|||
tile_size: LayerSize,
|
||||
tile_spacing: LayerSize,
|
||||
) {
|
||||
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||
self.cached_gradients.push(CachedGradient::new());
|
||||
|
||||
let prim_infos = info.decompose(
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
|
@ -1371,6 +1400,7 @@ impl FrameBuilder {
|
|||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
);
|
||||
} else {
|
||||
for prim_info in prim_infos {
|
||||
|
@ -1384,6 +1414,7 @@ impl FrameBuilder {
|
|||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1703,6 +1734,7 @@ impl FrameBuilder {
|
|||
local_clip_rects,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
cached_gradients: &mut self.cached_gradients,
|
||||
};
|
||||
|
||||
let pic_context = PictureContext {
|
||||
|
@ -1871,6 +1903,7 @@ impl FrameBuilder {
|
|||
clip_scroll_tree,
|
||||
use_dual_source_blending,
|
||||
node_data: &node_data,
|
||||
cached_gradients: &self.cached_gradients,
|
||||
};
|
||||
|
||||
pass.build(
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag};
|
||||
use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LayerToWorldTransform, LocalClip, PipelineId};
|
||||
use api::WorldPoint;
|
||||
use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LocalClip, PipelineId, WorldPoint};
|
||||
use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point};
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollTree};
|
||||
use internal_types::FastHashMap;
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use util::LayerToWorldFastTransform;
|
||||
|
||||
/// 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,
|
||||
|
@ -20,10 +20,10 @@ pub struct HitTestClipScrollNode {
|
|||
regions: Vec<HitTestRegion>,
|
||||
|
||||
/// 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: LayerToWorldTransform,
|
||||
world_viewport_transform: LayerToWorldFastTransform,
|
||||
|
||||
/// Origin of the viewport of the node, used to calculate node-relative positions.
|
||||
node_origin: LayerPoint,
|
||||
|
|
|
@ -7,7 +7,7 @@ use api::{LayerRect, LayerToWorldScale, LayerVector2D, MixBlendMode, PipelineId}
|
|||
use api::{PremultipliedColorF, Shadow};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
|
||||
use frame_builder::{FrameContext, FrameState, PictureState};
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||
use gpu_types::{BrushImageKind, PictureType};
|
||||
use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
|
@ -88,6 +88,10 @@ pub enum PictureKind {
|
|||
// rendering context.
|
||||
reference_frame_id: ClipId,
|
||||
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,
|
||||
reference_frame_id,
|
||||
real_local_rect: LayerRect::zero(),
|
||||
extra_gpu_data_handle: GpuCacheHandle::new(),
|
||||
},
|
||||
pipeline_id,
|
||||
cull_children: true,
|
||||
|
@ -333,6 +338,7 @@ impl PicturePrimitive {
|
|||
match self.kind {
|
||||
PictureKind::Image {
|
||||
ref mut secondary_render_task_id,
|
||||
ref mut extra_gpu_data_handle,
|
||||
composite_mode,
|
||||
..
|
||||
} => {
|
||||
|
@ -429,6 +435,15 @@ impl PicturePrimitive {
|
|||
pic_state.tasks.extend(pic_state_for_children.tasks);
|
||||
self.surface = None;
|
||||
} 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(
|
||||
RenderTaskLocation::Dynamic(None, prim_screen_rect.size),
|
||||
prim_index,
|
||||
|
@ -594,17 +609,10 @@ impl PicturePrimitive {
|
|||
// making this more efficient for the common case.
|
||||
match self.kind {
|
||||
PictureKind::TextShadow { .. } => {
|
||||
for _ in 0 .. 5 {
|
||||
request.push([0.0; 4]);
|
||||
}
|
||||
request.push([0.0; 4]);
|
||||
}
|
||||
PictureKind::Image { 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)) => {
|
||||
let amount = match filter {
|
||||
FilterOp::Contrast(amount) => amount,
|
||||
|
@ -623,23 +631,14 @@ impl PicturePrimitive {
|
|||
};
|
||||
|
||||
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, .. } => {
|
||||
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::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
|
||||
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 clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||
use clip_scroll_node::ClipScrollNode;
|
||||
|
@ -25,11 +25,11 @@ use resource_cache::{CacheItem, ImageProperties, ImageRequest, ResourceCache};
|
|||
use segment::SegmentBuilder;
|
||||
use std::{mem, usize};
|
||||
use std::rc::Rc;
|
||||
use util::{MatrixHelpers, calculate_screen_bounding_rect, pack_as_float};
|
||||
use util::recycle_vec;
|
||||
use util::{MatrixHelpers, WorldToLayerFastTransform, calculate_screen_bounding_rect};
|
||||
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)]
|
||||
pub struct ScrollNodeAndClipChain {
|
||||
|
@ -69,9 +69,20 @@ impl PrimitiveOpacity {
|
|||
is_opaque: alpha == 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accumulate(&mut self, alpha: f32) {
|
||||
self.is_opaque = self.is_opaque && alpha == 1.0;
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
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,
|
||||
Image,
|
||||
Border,
|
||||
AlignedGradient,
|
||||
AngleGradient,
|
||||
Picture,
|
||||
Brush,
|
||||
}
|
||||
|
@ -211,14 +220,23 @@ pub enum BrushKind {
|
|||
image_rendering: ImageRendering,
|
||||
},
|
||||
RadialGradient {
|
||||
gradient_index: CachedGradientIndex,
|
||||
stops_range: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
stops_handle: GpuCacheHandle,
|
||||
start_center: LayerPoint,
|
||||
end_center: LayerPoint,
|
||||
start_radius: f32,
|
||||
end_radius: f32,
|
||||
ratio_xy: f32,
|
||||
},
|
||||
LinearGradient {
|
||||
gradient_index: CachedGradientIndex,
|
||||
stops_range: ItemRange<GradientStop>,
|
||||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
reverse_stops: bool,
|
||||
start_point: LayerPoint,
|
||||
end_point: LayerPoint,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +247,8 @@ impl BrushKind {
|
|||
BrushKind::Picture |
|
||||
BrushKind::Image { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } => true,
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::LinearGradient { .. } => true,
|
||||
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Clear |
|
||||
|
@ -359,6 +378,20 @@ impl BrushPrimitive {
|
|||
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, .. } => {
|
||||
request.push([
|
||||
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
|
||||
pub const GRADIENT_DATA_FIRST_STOP: usize = 0;
|
||||
// The gradient entry index for the last color stop
|
||||
|
@ -670,7 +663,7 @@ impl TextRunPrimitiveCpu {
|
|||
pub fn get_font(
|
||||
&self,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
transform: Option<&LayerToWorldTransform>,
|
||||
transform: Option<LayerToWorldTransform>,
|
||||
) -> FontInstance {
|
||||
let mut font = self.font.clone();
|
||||
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() {
|
||||
font.render_mode = font.render_mode.limit_by(FontRenderMode::Alpha);
|
||||
} else {
|
||||
font.transform = FontTransform::from(transform).quantize();
|
||||
font.transform = FontTransform::from(&transform).quantize();
|
||||
}
|
||||
}
|
||||
font
|
||||
|
@ -688,7 +681,7 @@ impl TextRunPrimitiveCpu {
|
|||
&mut self,
|
||||
resource_cache: &mut ResourceCache,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
transform: Option<&LayerToWorldTransform>,
|
||||
transform: Option<LayerToWorldTransform>,
|
||||
display_list: &BuiltDisplayList,
|
||||
gpu_cache: &mut GpuCache,
|
||||
) {
|
||||
|
@ -937,8 +930,6 @@ pub enum PrimitiveContainer {
|
|||
TextRun(TextRunPrimitiveCpu),
|
||||
Image(ImagePrimitiveCpu),
|
||||
Border(BorderPrimitiveCpu),
|
||||
AlignedGradient(GradientPrimitiveCpu),
|
||||
AngleGradient(GradientPrimitiveCpu),
|
||||
Picture(PicturePrimitive),
|
||||
Brush(BrushPrimitive),
|
||||
}
|
||||
|
@ -949,7 +940,6 @@ pub struct PrimitiveStore {
|
|||
pub cpu_text_runs: Vec<TextRunPrimitiveCpu>,
|
||||
pub cpu_pictures: Vec<PicturePrimitive>,
|
||||
pub cpu_images: Vec<ImagePrimitiveCpu>,
|
||||
pub cpu_gradients: Vec<GradientPrimitiveCpu>,
|
||||
pub cpu_metadata: Vec<PrimitiveMetadata>,
|
||||
pub cpu_borders: Vec<BorderPrimitiveCpu>,
|
||||
}
|
||||
|
@ -962,7 +952,6 @@ impl PrimitiveStore {
|
|||
cpu_text_runs: Vec::new(),
|
||||
cpu_pictures: Vec::new(),
|
||||
cpu_images: Vec::new(),
|
||||
cpu_gradients: Vec::new(),
|
||||
cpu_borders: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -974,7 +963,6 @@ impl PrimitiveStore {
|
|||
cpu_text_runs: recycle_vec(self.cpu_text_runs),
|
||||
cpu_pictures: recycle_vec(self.cpu_pictures),
|
||||
cpu_images: recycle_vec(self.cpu_images),
|
||||
cpu_gradients: recycle_vec(self.cpu_gradients),
|
||||
cpu_borders: recycle_vec(self.cpu_borders),
|
||||
}
|
||||
}
|
||||
|
@ -1015,6 +1003,7 @@ impl PrimitiveStore {
|
|||
BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
|
||||
BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::LinearGradient { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Picture => {
|
||||
// TODO(gw): This is not currently used. In the future
|
||||
// we should detect opaque pictures.
|
||||
|
@ -1077,29 +1066,6 @@ impl PrimitiveStore {
|
|||
self.cpu_borders.push(border_cpu);
|
||||
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);
|
||||
|
@ -1146,7 +1112,7 @@ impl PrimitiveStore {
|
|||
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||
// The transform only makes sense for screen space rasterization
|
||||
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 {
|
||||
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) {
|
||||
let gradient_builder = GradientGpuBlockBuilder::new(
|
||||
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::Solid { .. } |
|
||||
BrushKind::Clear |
|
||||
|
@ -1323,8 +1303,6 @@ impl PrimitiveStore {
|
|||
BrushKind::Picture { .. } => {}
|
||||
}
|
||||
}
|
||||
PrimitiveKind::AlignedGradient |
|
||||
PrimitiveKind::AngleGradient => {}
|
||||
}
|
||||
|
||||
// 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];
|
||||
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 => {
|
||||
let text = &self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||
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 {
|
||||
local_clip_rect
|
||||
} else {
|
||||
let clip_transform_data = &frame_context
|
||||
.node_data[clip_item.scroll_node_data_index.0 as usize];
|
||||
let clip_transform = frame_context
|
||||
.node_data[clip_item.scroll_node_data_index.0 as usize]
|
||||
.transform;
|
||||
let prim_transform = &prim_run_context.scroll_node.world_content_transform;
|
||||
|
||||
let relative_transform = prim_transform
|
||||
.inverse()
|
||||
.unwrap_or(WorldToLayerTransform::identity())
|
||||
.pre_mul(&clip_transform_data.transform);
|
||||
.unwrap_or(WorldToLayerFastTransform::identity())
|
||||
.pre_mul(&clip_transform.into());
|
||||
|
||||
relative_transform.transform_rect(&local_clip_rect)
|
||||
};
|
||||
|
@ -2061,8 +2025,7 @@ fn get_local_clip_rect_for_nodes(
|
|||
);
|
||||
|
||||
match local_rect {
|
||||
Some(local_rect) =>
|
||||
Some(scroll_node.coordinate_system_relative_transform.unapply(&local_rect)),
|
||||
Some(local_rect) => scroll_node.coordinate_system_relative_transform.unapply(&local_rect),
|
||||
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(
|
||||
id,
|
||||
render_doc,
|
||||
|
|
|
@ -83,6 +83,10 @@ const GPU_CACHE_RESIZE_TEST: bool = false;
|
|||
/// Number of GPU blocks per UV rectangle provided for an image.
|
||||
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 {
|
||||
label: "B_RadialGradient",
|
||||
color: debug_colors::LIGHTPINK,
|
||||
|
@ -151,14 +155,6 @@ const GPU_TAG_PRIM_TEXT_RUN: GpuProfileTag = GpuProfileTag {
|
|||
label: "TextRun",
|
||||
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 {
|
||||
label: "BorderCorner",
|
||||
color: debug_colors::DARKSLATEGREY,
|
||||
|
@ -200,8 +196,6 @@ impl TransformBatchKind {
|
|||
ImageBufferKind::TextureExternal => "Image (External)",
|
||||
ImageBufferKind::Texture2DArray => "Image (Array)",
|
||||
},
|
||||
TransformBatchKind::AlignedGradient => "AlignedGradient",
|
||||
TransformBatchKind::AngleGradient => "AngleGradient",
|
||||
TransformBatchKind::BorderCorner => "BorderCorner",
|
||||
TransformBatchKind::BorderEdge => "BorderEdge",
|
||||
}
|
||||
|
@ -213,8 +207,6 @@ impl TransformBatchKind {
|
|||
TransformBatchKind::Image(..) => GPU_TAG_PRIM_IMAGE,
|
||||
TransformBatchKind::BorderCorner => GPU_TAG_PRIM_BORDER_CORNER,
|
||||
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::YuvImage(..) => "Brush (YuvImage)",
|
||||
BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
|
||||
BrushBatchKind::LinearGradient => "Brush (LinearGradient)",
|
||||
}
|
||||
}
|
||||
BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(),
|
||||
|
@ -255,6 +248,7 @@ impl BatchKind {
|
|||
BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
|
||||
BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
|
||||
BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
|
||||
BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
|
||||
}
|
||||
}
|
||||
BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(),
|
||||
|
@ -1618,6 +1612,7 @@ pub struct Renderer {
|
|||
brush_mix_blend: BrushShader,
|
||||
brush_yuv_image: Vec<Option<BrushShader>>,
|
||||
brush_radial_gradient: BrushShader,
|
||||
brush_linear_gradient: BrushShader,
|
||||
|
||||
/// These are "cache clip shaders". These shaders are used to
|
||||
/// draw clip instances into the cached clip mask. The results
|
||||
|
@ -1638,8 +1633,6 @@ pub struct Renderer {
|
|||
ps_image: Vec<Option<PrimitiveShader>>,
|
||||
ps_border_corner: PrimitiveShader,
|
||||
ps_border_edge: PrimitiveShader,
|
||||
ps_gradient: PrimitiveShader,
|
||||
ps_angle_gradient: PrimitiveShader,
|
||||
|
||||
ps_hw_composite: LazilyCompiledShader,
|
||||
ps_split_composite: LazilyCompiledShader,
|
||||
|
@ -1884,6 +1877,17 @@ impl Renderer {
|
|||
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!{
|
||||
LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur),
|
||||
"cs_blur",
|
||||
|
@ -2030,28 +2034,6 @@ impl Renderer {
|
|||
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!{
|
||||
LazilyCompiledShader::new(ShaderKind::Primitive,
|
||||
"ps_hardware_composite",
|
||||
|
@ -2303,6 +2285,7 @@ impl Renderer {
|
|||
brush_mix_blend,
|
||||
brush_yuv_image,
|
||||
brush_radial_gradient,
|
||||
brush_linear_gradient,
|
||||
cs_clip_rectangle,
|
||||
cs_clip_border,
|
||||
cs_clip_image,
|
||||
|
@ -2311,8 +2294,6 @@ impl Renderer {
|
|||
ps_image,
|
||||
ps_border_corner,
|
||||
ps_border_edge,
|
||||
ps_gradient,
|
||||
ps_angle_gradient,
|
||||
ps_hw_composite,
|
||||
ps_split_composite,
|
||||
debug: debug_renderer,
|
||||
|
@ -2892,7 +2873,9 @@ impl Renderer {
|
|||
for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents {
|
||||
frame.profile_counters.reset_targets();
|
||||
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(
|
||||
frame,
|
||||
|
@ -3272,6 +3255,15 @@ impl Renderer {
|
|||
&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) => {
|
||||
let shader_index =
|
||||
Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space);
|
||||
|
@ -3322,24 +3314,6 @@ impl Renderer {
|
|||
&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_mix_blend.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_image.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_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_split_composite.deinit(&mut self.device);
|
||||
#[cfg(feature = "capture")]
|
||||
|
|
|
@ -16,7 +16,7 @@ use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex};
|
|||
use gpu_types::{PrimitiveInstance};
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{PictureKind};
|
||||
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveStore};
|
||||
use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveKind, PrimitiveStore};
|
||||
use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask};
|
||||
use profiler::FrameProfileCounters;
|
||||
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
|
||||
|
@ -46,6 +46,7 @@ pub struct RenderTargetContext<'a> {
|
|||
pub clip_scroll_tree: &'a ClipScrollTree,
|
||||
pub use_dual_source_blending: bool,
|
||||
pub node_data: &'a [ClipScrollNodeData],
|
||||
pub cached_gradients: &'a [CachedGradient],
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -599,6 +600,7 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
BrushKind::Line { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::LinearGradient { .. } |
|
||||
BrushKind::Image { .. } => {
|
||||
unreachable!("bug: unexpected brush here");
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
|
||||
use api::{DevicePoint, DeviceRect, DeviceSize, LayerPoint, LayerRect, LayerSize};
|
||||
use api::{LayerToWorldTransform, LayerTransform, LayerVector2D, WorldRect};
|
||||
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, TypedTransform2D};
|
||||
use euclid::TypedTransform3D;
|
||||
use api::{DevicePoint, DeviceRect, DeviceSize, LayerPixel, LayerPoint, LayerRect, LayerSize};
|
||||
use api::{LayoutPixel, WorldPixel, WorldRect};
|
||||
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedPoint3D, TypedRect, TypedSize2D};
|
||||
use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D};
|
||||
use num_traits::Zero;
|
||||
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 transform_kind(&self) -> TransformedRectKind;
|
||||
fn is_simple_translation(&self) -> bool;
|
||||
fn is_simple_2d_translation(&self) -> bool;
|
||||
}
|
||||
|
||||
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.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>
|
||||
|
@ -145,7 +154,7 @@ pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
|
|||
}
|
||||
|
||||
pub fn calculate_screen_bounding_rect(
|
||||
transform: &LayerToWorldTransform,
|
||||
transform: &LayerToWorldFastTransform,
|
||||
rect: &LayerRect,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> DeviceIntRect {
|
||||
|
@ -334,67 +343,189 @@ impl MaxRect for DeviceRect {
|
|||
|
||||
/// An enum that tries to avoid expensive transformation matrix calculations
|
||||
/// when possible when dealing with non-perspective axis-aligned transformations.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TransformOrOffset {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FastTransform<Src, Dst> {
|
||||
/// 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
|
||||
/// 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.
|
||||
/// A 2D transformation with an inverse.
|
||||
Transform {
|
||||
transform: LayerTransform,
|
||||
inverse: Option<LayerTransform>,
|
||||
}
|
||||
transform: TypedTransform3D<f32, Src, Dst>,
|
||||
inverse: Option<TypedTransform3D<f32, Dst, Src>>,
|
||||
is_2d: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl TransformOrOffset {
|
||||
pub fn zero() -> TransformOrOffset {
|
||||
TransformOrOffset::Offset(LayerVector2D::zero())
|
||||
impl<Src, Dst> FastTransform<Src, Dst> {
|
||||
pub fn identity() -> Self {
|
||||
FastTransform::Offset(TypedVector2D::zero())
|
||||
}
|
||||
|
||||
fn new_transform(transform: LayerTransform) -> TransformOrOffset {
|
||||
if transform.is_2d() {
|
||||
TransformOrOffset::Transform {
|
||||
transform,
|
||||
inverse: Some(transform.inverse().expect("Expected invertible matrix."))
|
||||
pub fn with_vector(offset: TypedVector2D<f32, Src>) -> Self {
|
||||
FastTransform::Offset(offset)
|
||||
}
|
||||
|
||||
#[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 {
|
||||
FastTransform::Offset(offset) =>
|
||||
TypedTransform3D::create_translation(offset.x, offset.y, 0.0),
|
||||
FastTransform::Transform { transform, .. } => transform
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_invertible(&self) -> bool {
|
||||
match *self {
|
||||
FastTransform::Offset(..) => true,
|
||||
FastTransform::Transform { ref inverse, .. } => inverse.is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
} else {
|
||||
TransformOrOffset::Transform { transform, inverse: None }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply(&self, rect: &LayerRect) -> LayerRect {
|
||||
match *self {
|
||||
TransformOrOffset::Offset(offset) => rect.translate(&offset),
|
||||
TransformOrOffset::Transform {transform, .. } => transform.transform_rect(&rect),
|
||||
#[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()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unapply(&self, rect: &LayerRect) -> LayerRect {
|
||||
#[inline(always)]
|
||||
pub fn preserves_2d_axis_alignment(&self) -> bool {
|
||||
match *self {
|
||||
TransformOrOffset::Offset(offset) => rect.translate(&-offset),
|
||||
TransformOrOffset::Transform { inverse: Some(inverse), .. } =>
|
||||
inverse.transform_rect(&rect),
|
||||
TransformOrOffset::Transform { transform, inverse: None } =>
|
||||
transform.inverse_rect_footprint(rect),
|
||||
FastTransform::Offset(..) => true,
|
||||
FastTransform::Transform { ref transform, .. } =>
|
||||
transform.preserves_2d_axis_alignment(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self, new_offset: LayerVector2D) -> TransformOrOffset {
|
||||
#[inline(always)]
|
||||
pub fn has_perspective_component(&self) -> bool {
|
||||
match *self {
|
||||
TransformOrOffset::Offset(offset) => TransformOrOffset::Offset(offset + new_offset),
|
||||
TransformOrOffset::Transform { transform, .. } => {
|
||||
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());
|
||||
TransformOrOffset::new_transform(transform)
|
||||
FastTransform::with_transform(transform)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self, transform: LayerTransform) -> Option<TransformOrOffset> {
|
||||
if transform.is_simple_translation() {
|
||||
let offset = LayerVector2D::new(transform.m41, transform.m42);
|
||||
Some(self.offset(offset))
|
||||
pub fn post_translate(&self, new_offset: TypedVector2D<f32, Dst>) -> Self {
|
||||
match *self {
|
||||
FastTransform::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 {
|
||||
// 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.
|
||||
|
@ -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",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_gradient",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_angle_gradient",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_hardware_composite",
|
||||
features: PRIM_FEATURES,
|
||||
|
@ -81,7 +73,7 @@ const SHADERS: &[Shader] = &[
|
|||
// Brush shaders
|
||||
Shader {
|
||||
name: "brush_yuv_image",
|
||||
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED"],
|
||||
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED", "YUV_NV12,TEXTURE_RECT"],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_mask",
|
||||
|
@ -109,6 +101,10 @@ const SHADERS: &[Shader] = &[
|
|||
},
|
||||
Shader {
|
||||
name: "brush_radial_gradient",
|
||||
features: &[ "DITHERING" ],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_linear_gradient",
|
||||
features: &[],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -1 +1 @@
|
|||
e8d2ffb404a85651fe08a6d09abbece9bd2b9182
|
||||
8a19316a733a484bf9bafb8257e3008b1418bfe4
|
||||
|
|
Загрузка…
Ссылка в новой задаче