Bug 1439565 - Update webrender to commit 8a19316a733a484bf9bafb8257e3008b1418bfe4. r=jrmuizel

MozReview-Commit-ID: BZIK3GEG0ER

--HG--
extra : rebase_source : c24dbf123fe1732917e9fc57ee0ddfe2042892c4
This commit is contained in:
Kartikaya Gupta 2018-02-23 09:29:44 -05:00
Родитель 17ab2350ee
Коммит f22ca7ca1e
25 изменённых файлов: 651 добавлений и 661 удалений

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 5 #define VECS_PER_SPECIFIC_BRUSH 1
#define FORCE_NO_PERSPECTIVE #define FORCE_NO_PERSPECTIVE
#include shared,prim_shared,brush #include shared,prim_shared,brush
@ -83,9 +83,10 @@ void brush_vs(
} }
case 10: { case 10: {
// Color Matrix // Color Matrix
vec4 data[4] = fetch_from_resource_cache_4(prim_address + 1); vec4 mat_data[4] = fetch_from_resource_cache_4(user_data.z);
vColorMat = mat4(amount, data[0], data[1], data[2]); vec4 offset_data = fetch_from_resource_cache_1(user_data.z + 4);
vColorOffset = data[3]; vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]);
vColorOffset = offset_data;
break; break;
} }
default: break; default: break;

Просмотреть файл

@ -40,7 +40,12 @@ void brush_vs(
vUv.xy = mix(uv0, uv1, f); vUv.xy = mix(uv0, uv1, f);
vUv.xy /= texture_size; vUv.xy /= texture_size;
vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy; // Handle case where the UV coords are inverted (e.g. from an
// external image).
vUvBounds = vec4(
min(uv0, uv1) + vec2(0.5),
max(uv0, uv1) - vec2(0.5)
) / texture_size.xyxy;
#ifdef WR_FEATURE_ALPHA_PASS #ifdef WR_FEATURE_ALPHA_PASS
vLocalPos = vi.local_pos; vLocalPos = vi.local_pos;

Просмотреть файл

@ -119,38 +119,7 @@ void brush_vs(
#ifdef WR_FRAGMENT_SHADER #ifdef WR_FRAGMENT_SHADER
#define MAGIC_WAVY_LINE_AA_SNAP 0.7 #define MAGIC_WAVY_LINE_AA_SNAP 0.5
float det(vec2 a, vec2 b) {
return a.x * b.y - b.x * a.y;
}
// From: http://research.microsoft.com/en-us/um/people/hoppe/ravg.pdf
vec2 get_distance_vector(vec2 b0, vec2 b1, vec2 b2) {
float a = det(b0, b2);
float b = 2.0 * det(b1, b0);
float d = 2.0 * det(b2, b1);
float f = b * d - a * a;
vec2 d21 = b2 - b1;
vec2 d10 = b1 - b0;
vec2 d20 = b2 - b0;
vec2 gf = 2.0 * (b *d21 + d * d10 + a * d20);
gf = vec2(gf.y,-gf.x);
vec2 pp = -f * gf / dot(gf, gf);
vec2 d0p = b0 - pp;
float ap = det(d0p, d20);
float bp = 2.0 * det(d10, d0p);
float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);
return mix(mix(b0, b1, t), mix(b1,b2,t), t);
}
// Approximate distance from point to quadratic bezier.
float approx_distance(vec2 p, vec2 b0, vec2 b1, vec2 b2) {
return length(get_distance_vector(b0 - p, b1 - p, b2 - p));
}
vec4 brush_fs() { vec4 brush_fs() {
// Find the appropriate distance to apply the step over. // Find the appropriate distance to apply the step over.

Просмотреть файл

@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 2
#include shared,prim_shared,brush
flat varying int vGradientAddress;
flat varying float vGradientRepeat;
flat varying vec2 vScaledDir;
flat varying vec2 vStartPoint;
varying vec2 vPos;
#ifdef WR_FEATURE_ALPHA_PASS
varying vec2 vLocalPos;
#endif
#ifdef WR_VERTEX_SHADER
struct Gradient {
vec4 start_end_point;
vec4 extend_mode;
};
Gradient fetch_gradient(int address) {
vec4 data[2] = fetch_from_resource_cache_2(address);
return Gradient(data[0], data[1]);
}
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
ivec3 user_data,
PictureTask pic_task
) {
Gradient gradient = fetch_gradient(prim_address);
vPos = vi.local_pos - local_rect.p0;
vec2 start_point = gradient.start_end_point.xy;
vec2 end_point = gradient.start_end_point.zw;
vec2 dir = end_point - start_point;
vStartPoint = start_point;
vScaledDir = dir / dot(dir, dir);
vGradientAddress = user_data.x;
// Whether to repeat the gradient instead of clamping.
vGradientRepeat = float(int(gradient.extend_mode.x) != EXTEND_MODE_CLAMP);
#ifdef WR_FEATURE_ALPHA_PASS
vLocalPos = vi.local_pos;
#endif
}
#endif
#ifdef WR_FRAGMENT_SHADER
vec4 brush_fs() {
float offset = dot(vPos - vStartPoint, vScaledDir);
vec4 color = sample_gradient(vGradientAddress,
offset,
vGradientRepeat);
#ifdef WR_FEATURE_ALPHA_PASS
color *= init_transform_fs(vLocalPos);
#endif
return color;
}
#endif

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 5 #define VECS_PER_SPECIFIC_BRUSH 1
#include shared,prim_shared,brush #include shared,prim_shared,brush

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 5 #define VECS_PER_SPECIFIC_BRUSH 1
#include shared,prim_shared,brush #include shared,prim_shared,brush

Просмотреть файл

@ -41,6 +41,12 @@ varying vec2 vLocalPos;
flat varying vec4 vUvBounds_YUV; flat varying vec4 vUvBounds_YUV;
#endif #endif
#ifdef WR_FEATURE_TEXTURE_RECT
#define TEX_SIZE(sampler) vec2(1.0)
#else
#define TEX_SIZE(sampler) vec2(textureSize(sampler, 0).xy)
#endif
#ifdef WR_VERTEX_SHADER #ifdef WR_VERTEX_SHADER
void write_uv_rect( void write_uv_rect(
int resource_id, int resource_id,
@ -78,14 +84,14 @@ void brush_vs(
#endif #endif
#if defined (WR_FEATURE_YUV_PLANAR) #if defined (WR_FEATURE_YUV_PLANAR)
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_Y, vUvBounds_Y); write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
write_uv_rect(user_data.y, f, vec2(textureSize(sColor1, 0).xy), vUv_U, vUvBounds_U); write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
write_uv_rect(user_data.z, f, vec2(textureSize(sColor2, 0).xy), vUv_V, vUvBounds_V); write_uv_rect(user_data.z, f, TEX_SIZE(sColor2), vUv_V, vUvBounds_V);
#elif defined (WR_FEATURE_YUV_NV12) #elif defined (WR_FEATURE_YUV_NV12)
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_Y, vUvBounds_Y); write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
write_uv_rect(user_data.y, f, vec2(textureSize(sColor1, 0).xy), vUv_UV, vUvBounds_UV); write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_UV, vUvBounds_UV);
#elif defined (WR_FEATURE_YUV_INTERLEAVED) #elif defined (WR_FEATURE_YUV_INTERLEAVED)
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_YUV, vUvBounds_YUV); write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_YUV, vUvBounds_YUV);
#endif //WR_FEATURE_YUV_* #endif //WR_FEATURE_YUV_*
} }
#endif #endif

Просмотреть файл

@ -16,6 +16,8 @@
#define SUBPX_DIR_HORIZONTAL 1 #define SUBPX_DIR_HORIZONTAL 1
#define SUBPX_DIR_VERTICAL 2 #define SUBPX_DIR_VERTICAL 2
#define EPSILON 0.0001
uniform sampler2DArray sCacheA8; uniform sampler2DArray sCacheA8;
uniform sampler2DArray sCacheRGBA8; uniform sampler2DArray sCacheRGBA8;
@ -74,7 +76,6 @@ vec4[2] fetch_from_resource_cache_2(int address) {
#define VECS_PER_RENDER_TASK 3 #define VECS_PER_RENDER_TASK 3
#define VECS_PER_PRIM_HEADER 2 #define VECS_PER_PRIM_HEADER 2
#define VECS_PER_TEXT_RUN 3 #define VECS_PER_TEXT_RUN 3
#define VECS_PER_GRADIENT 3
#define VECS_PER_GRADIENT_STOP 2 #define VECS_PER_GRADIENT_STOP 2
uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes; uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes;
@ -304,17 +305,6 @@ ClipArea fetch_clip_area(int index) {
return area; return area;
} }
struct Gradient {
vec4 start_end_point;
vec4 tile_size_repeat;
vec4 extend_mode;
};
Gradient fetch_gradient(int address) {
vec4 data[3] = fetch_from_resource_cache_3(address);
return Gradient(data[0], data[1], data[2]);
}
struct Glyph { struct Glyph {
vec2 offset; vec2 offset;
}; };
@ -748,7 +738,7 @@ void write_clip(vec2 global_pos, ClipArea area) {
#ifdef WR_FRAGMENT_SHADER #ifdef WR_FRAGMENT_SHADER
/// Find the appropriate half range to apply the AA smoothstep over. /// Find the appropriate half range to apply the AA approximation over.
/// This range represents a coefficient to go from one CSS pixel to half a device pixel. /// This range represents a coefficient to go from one CSS pixel to half a device pixel.
float compute_aa_range(vec2 position) { float compute_aa_range(vec2 position) {
// The constant factor is chosen to compensate for the fact that length(fw) is equal // The constant factor is chosen to compensate for the fact that length(fw) is equal
@ -759,22 +749,41 @@ float compute_aa_range(vec2 position) {
// such a pixel (axis aligned) is fully inside the border). We need this so that antialiased // such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
// curves properly connect with non-antialiased vertical or horizontal lines, among other things. // curves properly connect with non-antialiased vertical or horizontal lines, among other things.
// //
// Using larger aa steps is quite common when rendering shapes with distance fields. // Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
// It gives a smoother (although blurrier look) by extending the range that is smoothed // indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
// to produce the anti aliasing. In our case, however, extending the range inside of // a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
// the shape causes noticeable artifacts at the junction between an antialiased corner // aliased corner and a straight edge.
// and a straight edge. //
// We may want to adjust this constant in specific scenarios (for example keep the principled // We may want to adjust this constant in specific scenarios (for example keep the principled
// value for straight edges where we want pixel-perfect equivalence with non antialiased lines // value for straight edges where we want pixel-perfect equivalence with non antialiased lines
// when axis aligned, while selecting a larger and smoother aa range on curves). // when axis aligned, while selecting a larger and smoother aa range on curves).
return 0.35355 * length(fwidth(position)); return 0.35355 * length(fwidth(position));
} }
/// Return the blending coefficient to for distance antialiasing. /// Return the blending coefficient for distance antialiasing.
/// ///
/// 0.0 means inside the shape, 1.0 means outside. /// 0.0 means inside the shape, 1.0 means outside.
///
/// This cubic polynomial approximates the area of a 1x1 pixel square under a
/// line, given the signed Euclidean distance from the center of the square to
/// that line. Calculating the *exact* area would require taking into account
/// not only this distance but also the angle of the line. However, in
/// practice, this complexity is not required, as the area is roughly the same
/// regardless of the angle.
///
/// The coefficients of this polynomial were determined through least-squares
/// regression and are accurate to within 2.16% of the total area of the pixel
/// square 95% of the time, with a maximum error of 3.53%.
///
/// See the comments in `compute_aa_range()` for more information on the
/// cutoff values of -0.5 and 0.5.
float distance_aa(float aa_range, float signed_distance) { float distance_aa(float aa_range, float signed_distance) {
return 1.0 - smoothstep(-aa_range, aa_range, signed_distance); float dist = 0.5 * signed_distance / aa_range;
if (dist <= -0.5 + EPSILON)
return 1.0;
if (dist >= 0.5 - EPSILON)
return 0.0;
return 0.5 + dist * (0.8431027 * dist * dist - 1.14453603);
} }
float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) { float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {

Просмотреть файл

@ -1,68 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include shared,prim_shared
flat varying int vGradientAddress;
flat varying float vGradientRepeat;
flat varying vec2 vScaledDir;
flat varying vec2 vStartPoint;
flat varying vec2 vTileSize;
flat varying vec2 vTileRepeat;
varying vec2 vPos;
#ifdef WR_VERTEX_SHADER
void main(void) {
Primitive prim = load_primitive();
Gradient gradient = fetch_gradient(prim.specific_prim_address);
VertexInfo vi = write_vertex(prim.local_rect,
prim.local_clip_rect,
prim.z,
prim.scroll_node,
prim.task,
prim.local_rect);
vPos = vi.local_pos - prim.local_rect.p0;
vec2 start_point = gradient.start_end_point.xy;
vec2 end_point = gradient.start_end_point.zw;
vec2 dir = end_point - start_point;
vStartPoint = start_point;
vScaledDir = dir / dot(dir, dir);
vTileSize = gradient.tile_size_repeat.xy;
vTileRepeat = gradient.tile_size_repeat.zw;
vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
// Whether to repeat the gradient instead of clamping.
vGradientRepeat = float(int(gradient.extend_mode.x) != EXTEND_MODE_CLAMP);
write_clip(vi.screen_pos, prim.clip_area);
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
vec2 pos = mod(vPos, vTileRepeat);
if (pos.x >= vTileSize.x ||
pos.y >= vTileSize.y) {
discard;
}
float offset = dot(pos - vStartPoint, vScaledDir);
vec4 color = sample_gradient(vGradientAddress,
offset,
vGradientRepeat);
oFragColor = color * do_clip();
}
#endif

Просмотреть файл

@ -1,119 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include shared,prim_shared
varying vec4 vColor;
varying vec2 vLocalPos;
#ifdef WR_VERTEX_SHADER
struct GradientStop {
vec4 color;
vec4 offset;
};
GradientStop fetch_gradient_stop(int address) {
vec4 data[2] = fetch_from_resource_cache_2(address);
return GradientStop(data[0], data[1]);
}
void main(void) {
Primitive prim = load_primitive();
Gradient gradient = fetch_gradient(prim.specific_prim_address);
vec4 abs_start_end_point = gradient.start_end_point + prim.local_rect.p0.xyxy;
int stop_address = prim.specific_prim_address +
VECS_PER_GRADIENT +
VECS_PER_GRADIENT_STOP * prim.user_data0;
GradientStop g0 = fetch_gradient_stop(stop_address);
GradientStop g1 = fetch_gradient_stop(stop_address + VECS_PER_GRADIENT_STOP);
RectWithSize segment_rect;
vec2 axis;
vec4 adjusted_color_g0 = g0.color;
vec4 adjusted_color_g1 = g1.color;
if (abs_start_end_point.y == abs_start_end_point.w) {
// Calculate the x coord of the gradient stops
vec2 g01_x = mix(abs_start_end_point.xx, abs_start_end_point.zz,
vec2(g0.offset.x, g1.offset.x));
// The gradient stops might exceed the geometry rect so clamp them
vec2 g01_x_clamped = clamp(g01_x,
prim.local_rect.p0.xx,
prim.local_rect.p0.xx + prim.local_rect.size.xx);
// Calculate the segment rect using the clamped coords
segment_rect.p0 = vec2(g01_x_clamped.x, prim.local_rect.p0.y);
segment_rect.size = vec2(g01_x_clamped.y - g01_x_clamped.x, prim.local_rect.size.y);
axis = vec2(1.0, 0.0);
// Adjust the stop colors by how much they were clamped
vec2 adjusted_offset = (g01_x_clamped - g01_x.xx) / (g01_x.y - g01_x.x);
adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
} else {
// Calculate the y coord of the gradient stops
vec2 g01_y = mix(abs_start_end_point.yy, abs_start_end_point.ww,
vec2(g0.offset.x, g1.offset.x));
// The gradient stops might exceed the geometry rect so clamp them
vec2 g01_y_clamped = clamp(g01_y,
prim.local_rect.p0.yy,
prim.local_rect.p0.yy + prim.local_rect.size.yy);
// Calculate the segment rect using the clamped coords
segment_rect.p0 = vec2(prim.local_rect.p0.x, g01_y_clamped.x);
segment_rect.size = vec2(prim.local_rect.size.x, g01_y_clamped.y - g01_y_clamped.x);
axis = vec2(0.0, 1.0);
// Adjust the stop colors by how much they were clamped
vec2 adjusted_offset = (g01_y_clamped - g01_y.xx) / (g01_y.y - g01_y.x);
adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
}
#ifdef WR_FEATURE_TRANSFORM
VertexInfo vi = write_transform_vertex(segment_rect,
prim.local_rect,
prim.local_clip_rect,
vec4(1.0),
prim.z,
prim.scroll_node,
prim.task,
true);
vLocalPos = vi.local_pos;
vec2 f = (vi.local_pos.xy - prim.local_rect.p0) / prim.local_rect.size;
#else
VertexInfo vi = write_vertex(segment_rect,
prim.local_clip_rect,
prim.z,
prim.scroll_node,
prim.task,
prim.local_rect);
vec2 f = (vi.local_pos - segment_rect.p0) / segment_rect.size;
vLocalPos = vi.local_pos;
#endif
write_clip(vi.screen_pos, prim.clip_area);
vColor = mix(adjusted_color_g0, adjusted_color_g1, dot(f, axis));
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
#ifdef WR_FEATURE_TRANSFORM
float alpha = init_transform_fs(vLocalPos);
#else
float alpha = 1.0;
#endif
alpha *= do_clip();
oFragColor = dither(vColor * alpha);
}
#endif

Просмотреть файл

@ -14,16 +14,9 @@
#include base #include base
// The textureLod() doesn't support samplerExternalOES for WR_FEATURE_TEXTURE_EXTERNAL.
// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external_essl3.txt
//
// The textureLod() doesn't support sampler2DRect for WR_FEATURE_TEXTURE_RECT, too.
//
// Use texture() instead.
#if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_RECT) || defined(WR_FEATURE_TEXTURE_2D) #if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_RECT) || defined(WR_FEATURE_TEXTURE_2D)
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy) #define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
#else #else
// In normal case, we use textureLod(). We haven't used the lod yet. So, we always pass 0.0 now.
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord) #define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord)
#endif #endif

Просмотреть файл

@ -18,7 +18,7 @@ use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveIn
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture}; use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface}; use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
use plane_split::{BspSplitter, Polygon, Splitter}; use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore}; use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun}; use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree}; use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
use renderer::{BlendMode, ImageBufferKind}; use renderer::{BlendMode, ImageBufferKind};
@ -38,8 +38,6 @@ const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fff);
pub enum TransformBatchKind { pub enum TransformBatchKind {
TextRun(GlyphFormat), TextRun(GlyphFormat),
Image(ImageBufferKind), Image(ImageBufferKind),
AlignedGradient,
AngleGradient,
BorderCorner, BorderCorner,
BorderEdge, BorderEdge,
} }
@ -78,6 +76,7 @@ pub enum BrushBatchKind {
}, },
YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace), YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace),
RadialGradient, RadialGradient,
LinearGradient,
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
@ -682,6 +681,7 @@ impl AlphaBatchBuilder {
ctx.resource_cache, ctx.resource_cache,
gpu_cache, gpu_cache,
deferred_resolves, deferred_resolves,
&ctx.cached_gradients,
) { ) {
self.add_brush_to_batch( self.add_brush_to_batch(
brush, brush,
@ -811,7 +811,7 @@ impl AlphaBatchBuilder {
let font_transform = if is_shadow { let font_transform = if is_shadow {
None None
} else { } else {
Some(&scroll_node.transform) Some(scroll_node.transform)
}; };
let font = text_cpu.get_font( let font = text_cpu.get_font(
@ -969,6 +969,7 @@ impl AlphaBatchBuilder {
is_in_3d_context, is_in_3d_context,
reference_frame_id, reference_frame_id,
real_local_rect, real_local_rect,
ref extra_gpu_data_handle,
.. ..
} => { } => {
// If this picture is participating in a 3D rendering context, // If this picture is participating in a 3D rendering context,
@ -977,8 +978,10 @@ impl AlphaBatchBuilder {
if is_in_3d_context { if is_in_3d_context {
// Push into parent plane splitter. // Push into parent plane splitter.
let real_xf = &ctx.clip_scroll_tree.nodes[&reference_frame_id].world_content_transform; let real_xf = &ctx.clip_scroll_tree
.nodes[&reference_frame_id]
.world_content_transform
.into();
let polygon = make_polygon( let polygon = make_polygon(
real_local_rect, real_local_rect,
&real_xf, &real_xf,
@ -1093,18 +1096,20 @@ impl AlphaBatchBuilder {
BatchTextures::render_target_cache(), BatchTextures::render_target_cache(),
); );
let filter_mode = match filter { let (filter_mode, extra_cache_address) = match filter {
FilterOp::Blur(..) => 0, FilterOp::Blur(..) => (0, 0),
FilterOp::Contrast(..) => 1, FilterOp::Contrast(..) => (1, 0),
FilterOp::Grayscale(..) => 2, FilterOp::Grayscale(..) => (2, 0),
FilterOp::HueRotate(..) => 3, FilterOp::HueRotate(..) => (3, 0),
FilterOp::Invert(..) => 4, FilterOp::Invert(..) => (4, 0),
FilterOp::Saturate(..) => 5, FilterOp::Saturate(..) => (5, 0),
FilterOp::Sepia(..) => 6, FilterOp::Sepia(..) => (6, 0),
FilterOp::Brightness(..) => 7, FilterOp::Brightness(..) => (7, 0),
FilterOp::Opacity(..) => 8, FilterOp::Opacity(..) => (8, 0),
FilterOp::DropShadow(..) => 9, FilterOp::DropShadow(..) => (9, 0),
FilterOp::ColorMatrix(..) => 10, FilterOp::ColorMatrix(..) => {
(10, extra_gpu_data_handle.as_int(gpu_cache))
}
}; };
let instance = BrushInstance { let instance = BrushInstance {
@ -1120,7 +1125,7 @@ impl AlphaBatchBuilder {
user_data: [ user_data: [
cache_task_address.0 as i32, cache_task_address.0 as i32,
filter_mode, filter_mode,
0, extra_cache_address,
], ],
}; };
@ -1206,28 +1211,6 @@ impl AlphaBatchBuilder {
} }
} }
} }
PrimitiveKind::AlignedGradient => {
let gradient_cpu =
&ctx.prim_store.cpu_gradients[prim_metadata.cpu_prim_index.0];
let kind = BatchKind::Transformable(
transform_kind,
TransformBatchKind::AlignedGradient,
);
let key = BatchKey::new(kind, non_segmented_blend_mode, no_textures);
let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
for part_index in 0 .. (gradient_cpu.stops_count - 1) {
batch.push(base_instance.build(part_index as i32, 0, 0));
}
}
PrimitiveKind::AngleGradient => {
let kind = BatchKind::Transformable(
transform_kind,
TransformBatchKind::AngleGradient,
);
let key = BatchKey::new(kind, non_segmented_blend_mode, no_textures);
let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
batch.push(base_instance.build(0, 0, 0));
}
} }
} }
@ -1330,6 +1313,7 @@ impl BrushPrimitive {
resource_cache: &ResourceCache, resource_cache: &ResourceCache,
gpu_cache: &mut GpuCache, gpu_cache: &mut GpuCache,
deferred_resolves: &mut Vec<DeferredResolve>, deferred_resolves: &mut Vec<DeferredResolve>,
cached_gradients: &[CachedGradient],
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> { ) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {
match self.kind { match self.kind {
BrushKind::Line { .. } => { BrushKind::Line { .. } => {
@ -1376,7 +1360,8 @@ impl BrushPrimitive {
[0; 3], [0; 3],
)) ))
} }
BrushKind::RadialGradient { ref stops_handle, .. } => { BrushKind::RadialGradient { gradient_index, .. } => {
let stops_handle = &cached_gradients[gradient_index.0].handle;
Some(( Some((
BrushBatchKind::RadialGradient, BrushBatchKind::RadialGradient,
BatchTextures::no_texture(), BatchTextures::no_texture(),
@ -1387,6 +1372,18 @@ impl BrushPrimitive {
], ],
)) ))
} }
BrushKind::LinearGradient { gradient_index, .. } => {
let stops_handle = &cached_gradients[gradient_index.0].handle;
Some((
BrushBatchKind::LinearGradient,
BatchTextures::no_texture(),
[
stops_handle.as_int(gpu_cache),
0,
0,
],
))
}
BrushKind::YuvImage { format, yuv_key, image_rendering, color_space } => { BrushKind::YuvImage { format, yuv_key, image_rendering, color_space } => {
let mut textures = BatchTextures::no_texture(); let mut textures = BatchTextures::no_texture();
let mut uv_rect_addresses = [0; 3]; let mut uv_rect_addresses = [0; 3];
@ -1464,8 +1461,6 @@ impl AlphaBatchHelpers for PrimitiveStore {
} }
PrimitiveKind::Border | PrimitiveKind::Border |
PrimitiveKind::AlignedGradient |
PrimitiveKind::AngleGradient |
PrimitiveKind::Picture => { PrimitiveKind::Picture => {
BlendMode::PremultipliedAlpha BlendMode::PremultipliedAlpha
} }
@ -1487,6 +1482,7 @@ impl AlphaBatchHelpers for PrimitiveStore {
BrushKind::Line { .. } | BrushKind::Line { .. } |
BrushKind::YuvImage { .. } | BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } | BrushKind::RadialGradient { .. } |
BrushKind::LinearGradient { .. } |
BrushKind::Picture => { BrushKind::Picture => {
BlendMode::PremultipliedAlpha BlendMode::PremultipliedAlpha
} }

Просмотреть файл

@ -3,8 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask}; use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
use api::{ImageRendering, LayerRect, LayerToWorldTransform, LayoutPoint, LayoutVector2D}; use api::{ImageRendering, LayerRect, LayoutPoint, LayoutVector2D, LocalClip};
use api::LocalClip;
use border::{BorderCornerClipSource, ensure_no_corner_overlap}; use border::{BorderCornerClipSource, ensure_no_corner_overlap};
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId}; use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
use ellipse::Ellipse; use ellipse::Ellipse;
@ -13,7 +12,8 @@ use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use gpu_types::ClipScrollNodeIndex; use gpu_types::ClipScrollNodeIndex;
use prim_store::{ClipData, ImageMaskData}; use prim_store::{ClipData, ImageMaskData};
use resource_cache::{ImageRequest, ResourceCache}; use resource_cache::{ImageRequest, ResourceCache};
use util::{MaxRect, MatrixHelpers, calculate_screen_bounding_rect, extract_inner_rect_safe}; use util::{LayerToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
use util::extract_inner_rect_safe;
use std::rc::Rc; use std::rc::Rc;
pub type ClipStore = FreeList<ClipSources>; pub type ClipStore = FreeList<ClipSources>;
@ -252,7 +252,7 @@ impl ClipSources {
pub fn get_screen_bounds( pub fn get_screen_bounds(
&self, &self,
transform: &LayerToWorldTransform, transform: &LayerToWorldFastTransform,
device_pixel_scale: DevicePixelScale, device_pixel_scale: DevicePixelScale,
) -> (DeviceIntRect, Option<DeviceIntRect>) { ) -> (DeviceIntRect, Option<DeviceIntRect>) {
// If this translation isn't axis aligned or has a perspective component, don't try to // If this translation isn't axis aligned or has a perspective component, don't try to

Просмотреть файл

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect}; use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect};
use api::{LayerSize, LayerToWorldTransform, LayerTransform, LayerVector2D, LayoutTransform}; use api::{LayerSize, LayerVector2D, LayoutTransform, LayoutVector2D, PipelineId, PropertyBinding};
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollEventPhase}; use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyOffsetBounds};
use api::{ScrollLocation, ScrollSensitivity, StickyOffsetBounds, WorldPoint}; use api::WorldPoint;
use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem}; use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem};
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState}; use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState};
use euclid::SideOffsets2D; use euclid::SideOffsets2D;
@ -15,7 +15,8 @@ use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData};
use resource_cache::ResourceCache; use resource_cache::ResourceCache;
use scene::SceneProperties; use scene::SceneProperties;
use spring::{DAMPING, STIFFNESS, Spring}; use spring::{DAMPING, STIFFNESS, Spring};
use util::{MatrixHelpers, TransformOrOffset, TransformedRectKind}; use util::{LayerToWorldFastTransform, LayerFastTransform, LayoutFastTransform};
use util::{TransformedRectKind};
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
const CAN_OVERSCROLL: bool = true; const CAN_OVERSCROLL: bool = true;
@ -91,10 +92,10 @@ pub struct ClipScrollNode {
/// between our reference frame and this node. For reference frames, we also include /// between our reference frame and this node. For reference frames, we also include
/// whatever local transformation this reference frame provides. This can be combined /// whatever local transformation this reference frame provides. This can be combined
/// with the local_viewport_rect to get its position in world space. /// with the local_viewport_rect to get its position in world space.
pub world_viewport_transform: LayerToWorldTransform, pub world_viewport_transform: LayerToWorldFastTransform,
/// World transform for content transformed by this node. /// World transform for content transformed by this node.
pub world_content_transform: LayerToWorldTransform, pub world_content_transform: LayerToWorldFastTransform,
/// Pipeline that this layer belongs to /// Pipeline that this layer belongs to
pub pipeline_id: PipelineId, pub pipeline_id: PipelineId,
@ -119,7 +120,7 @@ pub struct ClipScrollNode {
/// The transformation from the coordinate system which established our compatible coordinate /// The transformation from the coordinate system which established our compatible coordinate
/// system (same coordinate system id) and us. This can change via scroll offsets and via new /// system (same coordinate system id) and us. This can change via scroll offsets and via new
/// reference frame transforms. /// reference frame transforms.
pub coordinate_system_relative_transform: TransformOrOffset, pub coordinate_system_relative_transform: LayerFastTransform,
/// A linear ID / index of this clip-scroll node. Used as a reference to /// A linear ID / index of this clip-scroll node. Used as a reference to
/// pass to shaders, to allow them to fetch a given clip-scroll node. /// pass to shaders, to allow them to fetch a given clip-scroll node.
@ -135,15 +136,15 @@ impl ClipScrollNode {
) -> Self { ) -> Self {
ClipScrollNode { ClipScrollNode {
local_viewport_rect: *rect, local_viewport_rect: *rect,
world_viewport_transform: LayerToWorldTransform::identity(), world_viewport_transform: LayerToWorldFastTransform::identity(),
world_content_transform: LayerToWorldTransform::identity(), world_content_transform: LayerToWorldFastTransform::identity(),
parent: parent_id, parent: parent_id,
children: Vec::new(), children: Vec::new(),
pipeline_id, pipeline_id,
node_type: node_type, node_type: node_type,
invertible: true, invertible: true,
coordinate_system_id: CoordinateSystemId(0), coordinate_system_id: CoordinateSystemId(0),
coordinate_system_relative_transform: TransformOrOffset::zero(), coordinate_system_relative_transform: LayerFastTransform::identity(),
node_data_index: ClipScrollNodeIndex(0), node_data_index: ClipScrollNodeIndex(0),
} }
} }
@ -177,10 +178,12 @@ impl ClipScrollNode {
pipeline_id: PipelineId, pipeline_id: PipelineId,
) -> Self { ) -> Self {
let identity = LayoutTransform::identity(); let identity = LayoutTransform::identity();
let source_perspective = source_perspective.map_or_else(
LayoutFastTransform::identity, |perspective| perspective.into());
let info = ReferenceFrameInfo { let info = ReferenceFrameInfo {
resolved_transform: LayerTransform::identity(), resolved_transform: LayerFastTransform::identity(),
source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)), source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)),
source_perspective: source_perspective.unwrap_or(identity), source_perspective: source_perspective,
origin_in_parent_reference_frame, origin_in_parent_reference_frame,
invertible: true, invertible: true,
}; };
@ -258,8 +261,8 @@ impl ClipScrollNode {
pub fn mark_uninvertible(&mut self) { pub fn mark_uninvertible(&mut self) {
self.invertible = false; self.invertible = false;
self.world_content_transform = LayerToWorldTransform::identity(); self.world_content_transform = LayerToWorldFastTransform::identity();
self.world_viewport_transform = LayerToWorldTransform::identity(); self.world_viewport_transform = LayerToWorldFastTransform::identity();
} }
pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) { pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) {
@ -274,7 +277,7 @@ impl ClipScrollNode {
TransformedRectKind::Complex TransformedRectKind::Complex
}; };
let data = ClipScrollNodeData { let data = ClipScrollNodeData {
transform: self.world_content_transform, transform: self.world_content_transform.into(),
transform_kind: transform_kind as u32 as f32, transform_kind: transform_kind as u32 as f32,
padding: [0.0; 3], padding: [0.0; 3],
}; };
@ -303,9 +306,9 @@ impl ClipScrollNode {
self.update_transform(state, next_coordinate_system_id, scene_properties); self.update_transform(state, next_coordinate_system_id, scene_properties);
// If this node is a reference frame, we check if the determinant is 0, which means it // If this node is a reference frame, we check if it has a non-invertible matrix.
// has a non-invertible matrix. For non-reference-frames we assume that they will // For non-reference-frames we assume that they will produce only additional
// produce only additional translations which should be invertible. // translations which should be invertible.
match self.node_type { match self.node_type {
NodeType::ReferenceFrame(info) if !info.invertible => { NodeType::ReferenceFrame(info) if !info.invertible => {
self.mark_uninvertible(); self.mark_uninvertible();
@ -362,7 +365,7 @@ impl ClipScrollNode {
let mut clip_chain = clip_chains[state.parent_clip_chain_index.0].new_with_added_node( let mut clip_chain = clip_chains[state.parent_clip_chain_index.0].new_with_added_node(
work_item, work_item,
self.coordinate_system_relative_transform.apply(&local_outer_rect), self.coordinate_system_relative_transform.transform_rect(&local_outer_rect),
screen_outer_rect, screen_outer_rect,
screen_inner_rect, screen_inner_rect,
); );
@ -398,7 +401,7 @@ impl ClipScrollNode {
// provided by our own sticky positioning. // provided by our own sticky positioning.
let accumulated_offset = state.parent_accumulated_scroll_offset + sticky_offset; let accumulated_offset = state.parent_accumulated_scroll_offset + sticky_offset;
self.world_viewport_transform = if accumulated_offset != LayerVector2D::zero() { self.world_viewport_transform = if accumulated_offset != LayerVector2D::zero() {
state.parent_reference_frame_transform.pre_translate(accumulated_offset.to_3d()) state.parent_reference_frame_transform.pre_translate(&accumulated_offset)
} else { } else {
state.parent_reference_frame_transform state.parent_reference_frame_transform
}; };
@ -407,7 +410,7 @@ impl ClipScrollNode {
// whatever scrolling offset we supply as well. // whatever scrolling offset we supply as well.
let scroll_offset = self.scroll_offset(); let scroll_offset = self.scroll_offset();
self.world_content_transform = if scroll_offset != LayerVector2D::zero() { self.world_content_transform = if scroll_offset != LayerVector2D::zero() {
self.world_viewport_transform.pre_translate(scroll_offset.to_3d()) self.world_viewport_transform.pre_translate(&scroll_offset)
} else { } else {
self.world_viewport_transform self.world_viewport_transform
}; };
@ -437,12 +440,10 @@ impl ClipScrollNode {
// Resolve the transform against any property bindings. // Resolve the transform against any property bindings.
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform); let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
info.resolved_transform = LayerTransform::create_translation( info.resolved_transform =
info.origin_in_parent_reference_frame.x, LayerFastTransform::with_vector(info.origin_in_parent_reference_frame)
info.origin_in_parent_reference_frame.y, .pre_mul(&source_transform.into())
0.0 .pre_mul(&info.source_perspective);
).pre_mul(&source_transform)
.pre_mul(&info.source_perspective);
// The transformation for this viewport in world coordinates is the transformation for // The transformation for this viewport in world coordinates is the transformation for
// our parent reference frame, plus any accumulated scrolling offsets from nodes // 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 // whatever local transformation this reference frame provides. This can be combined
// with the local_viewport_rect to get its position in world space. // with the local_viewport_rect to get its position in world space.
let relative_transform = info.resolved_transform let relative_transform = info.resolved_transform
.post_translate(state.parent_accumulated_scroll_offset.to_3d()); .post_translate(state.parent_accumulated_scroll_offset)
self.world_viewport_transform = state.parent_reference_frame_transform .to_transform()
.pre_mul(&relative_transform.with_destination::<LayerPixel>()); .with_destination::<LayerPixel>();
self.world_viewport_transform =
state.parent_reference_frame_transform.pre_mul(&relative_transform.into());
self.world_content_transform = self.world_viewport_transform; self.world_content_transform = self.world_viewport_transform;
info.invertible = relative_transform.determinant() != 0.0; info.invertible = self.world_viewport_transform.is_invertible();
if !info.invertible { if !info.invertible {
return; return;
} }
@ -465,7 +468,7 @@ impl ClipScrollNode {
match state.coordinate_system_relative_transform.update(relative_transform) { match state.coordinate_system_relative_transform.update(relative_transform) {
Some(offset) => self.coordinate_system_relative_transform = offset, Some(offset) => self.coordinate_system_relative_transform = offset,
None => { None => {
self.coordinate_system_relative_transform = TransformOrOffset::zero(); self.coordinate_system_relative_transform = LayerFastTransform::identity();
state.current_coordinate_system_id = *next_coordinate_system_id; state.current_coordinate_system_id = *next_coordinate_system_id;
next_coordinate_system_id.advance(); next_coordinate_system_id.advance();
} }
@ -844,14 +847,14 @@ impl ScrollFrameInfo {
pub struct ReferenceFrameInfo { pub struct ReferenceFrameInfo {
/// The transformation that establishes this reference frame, relative to the parent /// The transformation that establishes this reference frame, relative to the parent
/// reference frame. The origin of the reference frame is included in the transformation. /// reference frame. The origin of the reference frame is included in the transformation.
pub resolved_transform: LayerTransform, pub resolved_transform: LayerFastTransform,
/// The source transform and perspective matrices provided by the stacking context /// The source transform and perspective matrices provided by the stacking context
/// that forms this reference frame. We maintain the property binding information /// that forms this reference frame. We maintain the property binding information
/// here so that we can resolve the animated transform and update the tree each /// here so that we can resolve the animated transform and update the tree each
/// frame. /// frame.
pub source_transform: PropertyBinding<LayoutTransform>, pub source_transform: PropertyBinding<LayoutTransform>,
pub source_perspective: LayoutTransform, pub source_perspective: LayoutFastTransform,
/// The original, not including the transform and relative to the parent reference frame, /// The original, not including the transform and relative to the parent reference frame,
/// origin of this reference frame. This is already rolled into the `transform' property, but /// origin of this reference frame. This is already rolled into the `transform' property, but

Просмотреть файл

@ -3,8 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect}; use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect};
use api::{LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase}; use api::{LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLocation};
use api::{ScrollLocation, ScrollNodeState, WorldPoint}; use api::{ScrollNodeState, WorldPoint};
use clip::{ClipChain, ClipSourcesHandle, ClipStore}; use clip::{ClipChain, ClipSourcesHandle, ClipStore};
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo}; use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo};
use gpu_cache::GpuCache; use gpu_cache::GpuCache;
@ -13,7 +13,7 @@ use internal_types::{FastHashMap, FastHashSet};
use print_tree::{PrintTree, PrintTreePrinter}; use print_tree::{PrintTree, PrintTreePrinter};
use resource_cache::ResourceCache; use resource_cache::ResourceCache;
use scene::SceneProperties; use scene::SceneProperties;
use util::TransformOrOffset; use util::{LayerFastTransform, LayerToWorldFastTransform};
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>; pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
@ -88,7 +88,7 @@ pub struct ClipScrollTree {
#[derive(Clone)] #[derive(Clone)]
pub struct TransformUpdateState { pub struct TransformUpdateState {
pub parent_reference_frame_transform: LayerToWorldTransform, pub parent_reference_frame_transform: LayerToWorldFastTransform,
pub parent_accumulated_scroll_offset: LayerVector2D, pub parent_accumulated_scroll_offset: LayerVector2D,
pub nearest_scrolling_ancestor_offset: LayerVector2D, pub nearest_scrolling_ancestor_offset: LayerVector2D,
pub nearest_scrolling_ancestor_viewport: LayerRect, pub nearest_scrolling_ancestor_viewport: LayerRect,
@ -103,7 +103,7 @@ pub struct TransformUpdateState {
pub current_coordinate_system_id: CoordinateSystemId, pub current_coordinate_system_id: CoordinateSystemId,
/// Transform from the coordinate system that started this compatible coordinate system. /// Transform from the coordinate system that started this compatible coordinate system.
pub coordinate_system_relative_transform: TransformOrOffset, pub coordinate_system_relative_transform: LayerFastTransform,
/// True if this node is transformed by an invertible transform. If not, display items /// True if this node is transformed by an invertible transform. If not, display items
/// transformed by this node will not be displayed and display items not transformed by this /// transformed by this node will not be displayed and display items not transformed by this
@ -329,17 +329,13 @@ impl ClipScrollTree {
let root_reference_frame_id = self.root_reference_frame_id(); let root_reference_frame_id = self.root_reference_frame_id();
let mut state = TransformUpdateState { let mut state = TransformUpdateState {
parent_reference_frame_transform: LayerToWorldTransform::create_translation( parent_reference_frame_transform: LayerVector2D::new(pan.x, pan.y).into(),
pan.x,
pan.y,
0.0,
),
parent_accumulated_scroll_offset: LayerVector2D::zero(), parent_accumulated_scroll_offset: LayerVector2D::zero(),
nearest_scrolling_ancestor_offset: LayerVector2D::zero(), nearest_scrolling_ancestor_offset: LayerVector2D::zero(),
nearest_scrolling_ancestor_viewport: LayerRect::zero(), nearest_scrolling_ancestor_viewport: LayerRect::zero(),
parent_clip_chain_index: ClipChainIndex(0), parent_clip_chain_index: ClipChainIndex(0),
current_coordinate_system_id: CoordinateSystemId::root(), current_coordinate_system_id: CoordinateSystemId::root(),
coordinate_system_relative_transform: TransformOrOffset::zero(), coordinate_system_relative_transform: LayerFastTransform::identity(),
invertible: true, invertible: true,
}; };
let mut next_coordinate_system_id = state.current_coordinate_system_id.next(); let mut next_coordinate_system_id = state.current_coordinate_system_id.next();

Просмотреть файл

@ -6,11 +6,10 @@ use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, ClipId,
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint}; use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint};
use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId}; use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId};
use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering}; use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering};
use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerTransform}; use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D};
use api::{LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip}; use api::{LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip, PipelineId};
use api::{PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow}; use api::{PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow, TexelRect};
use api::{TexelRect, TileOffset, TransformStyle, WorldPoint, WorldToLayerTransform, YuvColorSpace}; use api::{TileOffset, TransformStyle, WorldPoint, YuvColorSpace, YuvData};
use api::YuvData;
use app_units::Au; use app_units::Au;
use border::ImageBorderSegment; use border::ImageBorderSegment;
use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore}; use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore};
@ -19,12 +18,12 @@ use clip_scroll_tree::{ClipScrollTree, ClipChainIndex};
use euclid::{SideOffsets2D, vec2}; use euclid::{SideOffsets2D, vec2};
use frame::{FrameId, ClipIdToIndexMapper}; use frame::{FrameId, ClipIdToIndexMapper};
use glyph_rasterizer::FontInstance; use glyph_rasterizer::FontInstance;
use gpu_cache::{GpuCache, GpuCacheHandle}; use gpu_cache::GpuCache;
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType}; use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
use hit_test::{HitTester, HitTestingItem, HitTestingRun}; use hit_test::{HitTester, HitTestingItem, HitTestingRun};
use internal_types::{FastHashMap, FastHashSet}; use internal_types::{FastHashMap, FastHashSet};
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface}; use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, GradientPrimitiveCpu}; use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, CachedGradient, CachedGradientIndex};
use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer}; use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer};
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore}; use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore};
use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu}; use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
@ -35,7 +34,7 @@ use scene::{ScenePipeline, SceneProperties};
use std::{mem, usize, f32}; use std::{mem, usize, f32};
use tiling::{CompositeOps, Frame, RenderPass, RenderTargetKind}; use tiling::{CompositeOps, Frame, RenderPass, RenderTargetKind};
use tiling::{RenderPassKind, RenderTargetContext, ScrollbarPrimitive}; use tiling::{RenderPassKind, RenderTargetContext, ScrollbarPrimitive};
use util::{self, MaxRect, pack_as_float, RectHelpers, recycle_vec}; use util::{self, MaxRect, RectHelpers, WorldToLayerFastTransform, recycle_vec};
#[derive(Debug)] #[derive(Debug)]
pub struct ScrollbarInfo(pub ClipId, pub LayerRect); pub struct ScrollbarInfo(pub ClipId, pub LayerRect);
@ -86,6 +85,7 @@ pub struct FrameBuilder {
pub clip_store: ClipStore, pub clip_store: ClipStore,
hit_testing_runs: Vec<HitTestingRun>, hit_testing_runs: Vec<HitTestingRun>,
pub config: FrameBuilderConfig, pub config: FrameBuilderConfig,
pub cached_gradients: Vec<CachedGradient>,
// A stack of the current shadow primitives. // A stack of the current shadow primitives.
// The sub-Vec stores a buffer of fast-path primitives to be appended on pop. // The sub-Vec stores a buffer of fast-path primitives to be appended on pop.
@ -124,6 +124,7 @@ pub struct FrameState<'a> {
pub local_clip_rects: &'a mut Vec<LayerRect>, pub local_clip_rects: &'a mut Vec<LayerRect>,
pub resource_cache: &'a mut ResourceCache, pub resource_cache: &'a mut ResourceCache,
pub gpu_cache: &'a mut GpuCache, pub gpu_cache: &'a mut GpuCache,
pub cached_gradients: &'a mut [CachedGradient],
} }
pub struct PictureContext<'a> { pub struct PictureContext<'a> {
@ -133,7 +134,7 @@ pub struct PictureContext<'a> {
pub original_reference_frame_id: Option<ClipId>, pub original_reference_frame_id: Option<ClipId>,
pub display_list: &'a BuiltDisplayList, pub display_list: &'a BuiltDisplayList,
pub draw_text_transformed: bool, pub draw_text_transformed: bool,
pub inv_world_transform: Option<WorldToLayerTransform>, pub inv_world_transform: Option<WorldToLayerFastTransform>,
} }
pub struct PictureState { pub struct PictureState {
@ -173,6 +174,7 @@ impl FrameBuilder {
FrameBuilder { FrameBuilder {
hit_testing_runs: Vec::new(), hit_testing_runs: Vec::new(),
shadow_prim_stack: Vec::new(), shadow_prim_stack: Vec::new(),
cached_gradients: Vec::new(),
pending_shadow_contents: Vec::new(), pending_shadow_contents: Vec::new(),
scrollbar_prims: Vec::new(), scrollbar_prims: Vec::new(),
reference_frame_stack: Vec::new(), reference_frame_stack: Vec::new(),
@ -201,6 +203,7 @@ impl FrameBuilder {
FrameBuilder { FrameBuilder {
hit_testing_runs: recycle_vec(self.hit_testing_runs), hit_testing_runs: recycle_vec(self.hit_testing_runs),
shadow_prim_stack: recycle_vec(self.shadow_prim_stack), shadow_prim_stack: recycle_vec(self.shadow_prim_stack),
cached_gradients: recycle_vec(self.cached_gradients),
pending_shadow_contents: recycle_vec(self.pending_shadow_contents), pending_shadow_contents: recycle_vec(self.pending_shadow_contents),
scrollbar_prims: recycle_vec(self.scrollbar_prims), scrollbar_prims: recycle_vec(self.scrollbar_prims),
reference_frame_stack: recycle_vec(self.reference_frame_stack), reference_frame_stack: recycle_vec(self.reference_frame_stack),
@ -673,11 +676,8 @@ impl FrameBuilder {
let root_id = clip_scroll_tree.root_reference_frame_id(); let root_id = clip_scroll_tree.root_reference_frame_id();
if let Some(root_node) = clip_scroll_tree.nodes.get_mut(&root_id) { if let Some(root_node) = clip_scroll_tree.nodes.get_mut(&root_id) {
if let NodeType::ReferenceFrame(ref mut info) = root_node.node_type { if let NodeType::ReferenceFrame(ref mut info) = root_node.node_type {
info.resolved_transform = LayerTransform::create_translation( info.resolved_transform =
viewport_offset.x, LayerVector2D::new(viewport_offset.x, viewport_offset.y).into();
viewport_offset.y,
0.0,
);
} }
} }
} }
@ -1236,6 +1236,53 @@ impl FrameBuilder {
} }
} }
fn add_gradient_impl(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
info: &LayerPrimitiveInfo,
start_point: LayerPoint,
end_point: LayerPoint,
stops: ItemRange<GradientStop>,
stops_count: usize,
extend_mode: ExtendMode,
gradient_index: CachedGradientIndex,
) {
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
// are also supplied in reverse that the rendered result will be equivalent. To do this,
// a reference orientation for the gradient line must be chosen, somewhat arbitrarily, so
// just designate the reference orientation as start < end. Aligned gradient rendering
// manages to produce the same result regardless of orientation, so don't worry about
// reversing in that case.
let reverse_stops = start_point.x > end_point.x ||
(start_point.x == end_point.x && start_point.y > end_point.y);
// To get reftests exactly matching with reverse start/end
// points, it's necessary to reverse the gradient
// line in some cases.
let (sp, ep) = if reverse_stops {
(end_point, start_point)
} else {
(start_point, end_point)
};
let prim = BrushPrimitive::new(
BrushKind::LinearGradient {
stops_range: stops,
stops_count,
extend_mode,
reverse_stops,
start_point: sp,
end_point: ep,
gradient_index,
},
None,
);
let prim = PrimitiveContainer::Brush(prim);
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
}
pub fn add_gradient( pub fn add_gradient(
&mut self, &mut self,
clip_and_scroll: ScrollNodeAndClipChain, clip_and_scroll: ScrollNodeAndClipChain,
@ -1248,62 +1295,40 @@ impl FrameBuilder {
tile_size: LayerSize, tile_size: LayerSize,
tile_spacing: LayerSize, tile_spacing: LayerSize,
) { ) {
let tile_repeat = tile_size + tile_spacing; let gradient_index = CachedGradientIndex(self.cached_gradients.len());
let is_not_tiled = tile_repeat.width >= info.rect.size.width && self.cached_gradients.push(CachedGradient::new());
tile_repeat.height >= info.rect.size.height;
let aligned_and_fills_rect = (start_point.x == end_point.x && let prim_infos = info.decompose(
start_point.y.min(end_point.y) <= 0.0 && tile_size,
start_point.y.max(end_point.y) >= info.rect.size.height) || tile_spacing,
(start_point.y == end_point.y && start_point.x.min(end_point.x) <= 0.0 && 64 * 64,
start_point.x.max(end_point.x) >= info.rect.size.width); );
// Fast path for clamped, axis-aligned gradients, with gradient lines intersecting all of rect: if prim_infos.is_empty() {
let aligned = extend_mode == ExtendMode::Clamp && is_not_tiled && aligned_and_fills_rect; self.add_gradient_impl(
clip_and_scroll,
// Try to ensure that if the gradient is specified in reverse, then so long as the stops info,
// are also supplied in reverse that the rendered result will be equivalent. To do this, start_point,
// a reference orientation for the gradient line must be chosen, somewhat arbitrarily, so end_point,
// just designate the reference orientation as start < end. Aligned gradient rendering stops,
// manages to produce the same result regardless of orientation, so don't worry about stops_count,
// reversing in that case. extend_mode,
let reverse_stops = !aligned && gradient_index,
(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 { } else {
(start_point, end_point) for prim_info in prim_infos {
}; self.add_gradient_impl(
clip_and_scroll,
let gradient_cpu = GradientPrimitiveCpu { &prim_info,
stops_range: stops, start_point,
stops_count, end_point,
extend_mode, stops,
reverse_stops, stops_count,
gpu_blocks: [ extend_mode,
[sp.x, sp.y, ep.x, ep.y].into(), gradient_index,
[ );
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);
} }
fn add_radial_gradient_impl( fn add_radial_gradient_impl(
@ -1317,17 +1342,18 @@ impl FrameBuilder {
ratio_xy: f32, ratio_xy: f32,
stops: ItemRange<GradientStop>, stops: ItemRange<GradientStop>,
extend_mode: ExtendMode, extend_mode: ExtendMode,
gradient_index: CachedGradientIndex,
) { ) {
let prim = BrushPrimitive::new( let prim = BrushPrimitive::new(
BrushKind::RadialGradient { BrushKind::RadialGradient {
stops_range: stops, stops_range: stops,
extend_mode, extend_mode,
stops_handle: GpuCacheHandle::new(),
start_center, start_center,
end_center, end_center,
start_radius, start_radius,
end_radius, end_radius,
ratio_xy, ratio_xy,
gradient_index,
}, },
None, None,
); );
@ -1354,6 +1380,9 @@ impl FrameBuilder {
tile_size: LayerSize, tile_size: LayerSize,
tile_spacing: LayerSize, tile_spacing: LayerSize,
) { ) {
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
self.cached_gradients.push(CachedGradient::new());
let prim_infos = info.decompose( let prim_infos = info.decompose(
tile_size, tile_size,
tile_spacing, tile_spacing,
@ -1371,6 +1400,7 @@ impl FrameBuilder {
ratio_xy, ratio_xy,
stops, stops,
extend_mode, extend_mode,
gradient_index,
); );
} else { } else {
for prim_info in prim_infos { for prim_info in prim_infos {
@ -1384,6 +1414,7 @@ impl FrameBuilder {
ratio_xy, ratio_xy,
stops, stops,
extend_mode, extend_mode,
gradient_index,
); );
} }
} }
@ -1703,6 +1734,7 @@ impl FrameBuilder {
local_clip_rects, local_clip_rects,
resource_cache, resource_cache,
gpu_cache, gpu_cache,
cached_gradients: &mut self.cached_gradients,
}; };
let pic_context = PictureContext { let pic_context = PictureContext {
@ -1871,6 +1903,7 @@ impl FrameBuilder {
clip_scroll_tree, clip_scroll_tree,
use_dual_source_blending, use_dual_source_blending,
node_data: &node_data, node_data: &node_data,
cached_gradients: &self.cached_gradients,
}; };
pass.build( pass.build(

Просмотреть файл

@ -3,13 +3,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag}; use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag};
use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LayerToWorldTransform, LocalClip, PipelineId}; use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LocalClip, PipelineId, WorldPoint};
use api::WorldPoint;
use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point}; use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point};
use clip_scroll_node::{ClipScrollNode, NodeType}; use clip_scroll_node::{ClipScrollNode, NodeType};
use clip_scroll_tree::{ClipChainIndex, ClipScrollTree}; use clip_scroll_tree::{ClipChainIndex, ClipScrollTree};
use internal_types::FastHashMap; use internal_types::FastHashMap;
use prim_store::ScrollNodeAndClipChain; use prim_store::ScrollNodeAndClipChain;
use util::LayerToWorldFastTransform;
/// A copy of important clip scroll node data to use during hit testing. This a copy of /// A copy of important clip scroll node data to use during hit testing. This a copy of
/// data from the ClipScrollTree that will persist as a new frame is under construction, /// data from the ClipScrollTree that will persist as a new frame is under construction,
@ -20,10 +20,10 @@ pub struct HitTestClipScrollNode {
regions: Vec<HitTestRegion>, regions: Vec<HitTestRegion>,
/// World transform for content transformed by this node. /// World transform for content transformed by this node.
world_content_transform: LayerToWorldTransform, world_content_transform: LayerToWorldFastTransform,
/// World viewport transform for content transformed by this node. /// World viewport transform for content transformed by this node.
world_viewport_transform: LayerToWorldTransform, world_viewport_transform: LayerToWorldFastTransform,
/// Origin of the viewport of the node, used to calculate node-relative positions. /// Origin of the viewport of the node, used to calculate node-relative positions.
node_origin: LayerPoint, node_origin: LayerPoint,

Просмотреть файл

@ -7,7 +7,7 @@ use api::{LayerRect, LayerToWorldScale, LayerVector2D, MixBlendMode, PipelineId}
use api::{PremultipliedColorF, Shadow}; use api::{PremultipliedColorF, Shadow};
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey}; use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
use frame_builder::{FrameContext, FrameState, PictureState}; use frame_builder::{FrameContext, FrameState, PictureState};
use gpu_cache::GpuDataRequest; use gpu_cache::{GpuCacheHandle, GpuDataRequest};
use gpu_types::{BrushImageKind, PictureType}; use gpu_types::{BrushImageKind, PictureType};
use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect}; use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
use prim_store::ScrollNodeAndClipChain; use prim_store::ScrollNodeAndClipChain;
@ -88,6 +88,10 @@ pub enum PictureKind {
// rendering context. // rendering context.
reference_frame_id: ClipId, reference_frame_id: ClipId,
real_local_rect: LayerRect, real_local_rect: LayerRect,
// An optional cache handle for storing extra data
// in the GPU cache, depending on the type of
// picture.
extra_gpu_data_handle: GpuCacheHandle,
}, },
} }
@ -217,6 +221,7 @@ impl PicturePrimitive {
frame_output_pipeline_id, frame_output_pipeline_id,
reference_frame_id, reference_frame_id,
real_local_rect: LayerRect::zero(), real_local_rect: LayerRect::zero(),
extra_gpu_data_handle: GpuCacheHandle::new(),
}, },
pipeline_id, pipeline_id,
cull_children: true, cull_children: true,
@ -333,6 +338,7 @@ impl PicturePrimitive {
match self.kind { match self.kind {
PictureKind::Image { PictureKind::Image {
ref mut secondary_render_task_id, ref mut secondary_render_task_id,
ref mut extra_gpu_data_handle,
composite_mode, composite_mode,
.. ..
} => { } => {
@ -429,6 +435,15 @@ impl PicturePrimitive {
pic_state.tasks.extend(pic_state_for_children.tasks); pic_state.tasks.extend(pic_state_for_children.tasks);
self.surface = None; self.surface = None;
} else { } else {
if let FilterOp::ColorMatrix(m) = filter {
if let Some(mut request) = frame_state.gpu_cache.request(extra_gpu_data_handle) {
for i in 0..5 {
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
}
}
}
let picture_task = RenderTask::new_picture( let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, prim_screen_rect.size), RenderTaskLocation::Dynamic(None, prim_screen_rect.size),
prim_index, prim_index,
@ -594,17 +609,10 @@ impl PicturePrimitive {
// making this more efficient for the common case. // making this more efficient for the common case.
match self.kind { match self.kind {
PictureKind::TextShadow { .. } => { PictureKind::TextShadow { .. } => {
for _ in 0 .. 5 { request.push([0.0; 4]);
request.push([0.0; 4]);
}
} }
PictureKind::Image { composite_mode, .. } => { PictureKind::Image { composite_mode, .. } => {
match composite_mode { match composite_mode {
Some(PictureCompositeMode::Filter(FilterOp::ColorMatrix(m))) => {
for i in 0..5 {
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
}
}
Some(PictureCompositeMode::Filter(filter)) => { Some(PictureCompositeMode::Filter(filter)) => {
let amount = match filter { let amount = match filter {
FilterOp::Contrast(amount) => amount, FilterOp::Contrast(amount) => amount,
@ -623,23 +631,14 @@ impl PicturePrimitive {
}; };
request.push([amount, 1.0 - amount, 0.0, 0.0]); request.push([amount, 1.0 - amount, 0.0, 0.0]);
for _ in 0 .. 4 {
request.push([0.0; 4]);
}
} }
_ => { _ => {
for _ in 0 .. 5 { request.push([0.0; 4]);
request.push([0.0; 4]);
}
} }
} }
} }
PictureKind::BoxShadow { color, .. } => { PictureKind::BoxShadow { color, .. } => {
request.push(color.premultiplied()); request.push(color.premultiplied());
for _ in 0 .. 4 {
request.push([0.0; 4]);
}
} }
} }
} }

Просмотреть файл

@ -6,7 +6,7 @@ use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipId, ClipMode, ColorF, C
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode}; use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode};
use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag}; use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation}; use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation};
use api::{LineStyle, PremultipliedColorF, WorldToLayerTransform, YuvColorSpace, YuvFormat}; use api::{LineStyle, PremultipliedColorF, YuvColorSpace, YuvFormat};
use border::{BorderCornerInstance, BorderEdgeKind}; use border::{BorderCornerInstance, BorderEdgeKind};
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId}; use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
use clip_scroll_node::ClipScrollNode; use clip_scroll_node::ClipScrollNode;
@ -25,11 +25,11 @@ use resource_cache::{CacheItem, ImageProperties, ImageRequest, ResourceCache};
use segment::SegmentBuilder; use segment::SegmentBuilder;
use std::{mem, usize}; use std::{mem, usize};
use std::rc::Rc; use std::rc::Rc;
use util::{MatrixHelpers, calculate_screen_bounding_rect, pack_as_float}; use util::{MatrixHelpers, WorldToLayerFastTransform, calculate_screen_bounding_rect};
use util::recycle_vec; use util::{pack_as_float, recycle_vec};
const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0; const MIN_BRUSH_SPLIT_AREA: f32 = 256.0 * 256.0;
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ScrollNodeAndClipChain { pub struct ScrollNodeAndClipChain {
@ -69,9 +69,20 @@ impl PrimitiveOpacity {
is_opaque: alpha == 1.0, is_opaque: alpha == 1.0,
} }
} }
}
pub fn accumulate(&mut self, alpha: f32) { #[derive(Debug, Copy, Clone)]
self.is_opaque = self.is_opaque && alpha == 1.0; pub struct CachedGradientIndex(pub usize);
pub struct CachedGradient {
pub handle: GpuCacheHandle,
}
impl CachedGradient {
pub fn new() -> CachedGradient {
CachedGradient {
handle: GpuCacheHandle::new(),
}
} }
} }
@ -124,8 +135,6 @@ pub enum PrimitiveKind {
TextRun, TextRun,
Image, Image,
Border, Border,
AlignedGradient,
AngleGradient,
Picture, Picture,
Brush, Brush,
} }
@ -211,14 +220,23 @@ pub enum BrushKind {
image_rendering: ImageRendering, image_rendering: ImageRendering,
}, },
RadialGradient { RadialGradient {
gradient_index: CachedGradientIndex,
stops_range: ItemRange<GradientStop>, stops_range: ItemRange<GradientStop>,
extend_mode: ExtendMode, extend_mode: ExtendMode,
stops_handle: GpuCacheHandle,
start_center: LayerPoint, start_center: LayerPoint,
end_center: LayerPoint, end_center: LayerPoint,
start_radius: f32, start_radius: f32,
end_radius: f32, end_radius: f32,
ratio_xy: f32, ratio_xy: f32,
},
LinearGradient {
gradient_index: CachedGradientIndex,
stops_range: ItemRange<GradientStop>,
stops_count: usize,
extend_mode: ExtendMode,
reverse_stops: bool,
start_point: LayerPoint,
end_point: LayerPoint,
} }
} }
@ -229,7 +247,8 @@ impl BrushKind {
BrushKind::Picture | BrushKind::Picture |
BrushKind::Image { .. } | BrushKind::Image { .. } |
BrushKind::YuvImage { .. } | BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } => true, BrushKind::RadialGradient { .. } |
BrushKind::LinearGradient { .. } => true,
BrushKind::Mask { .. } | BrushKind::Mask { .. } |
BrushKind::Clear | BrushKind::Clear |
@ -359,6 +378,20 @@ impl BrushPrimitive {
0.0, 0.0,
]); ]);
} }
BrushKind::LinearGradient { start_point, end_point, extend_mode, .. } => {
request.push([
start_point.x,
start_point.y,
end_point.x,
end_point.y,
]);
request.push([
pack_as_float(extend_mode as u32),
0.0,
0.0,
0.0,
]);
}
BrushKind::RadialGradient { start_center, end_center, start_radius, end_radius, ratio_xy, extend_mode, .. } => { BrushKind::RadialGradient { start_center, end_center, start_radius, end_radius, ratio_xy, extend_mode, .. } => {
request.push([ request.push([
start_center.x, start_center.x,
@ -432,46 +465,6 @@ impl ToGpuBlocks for BorderPrimitiveCpu {
} }
} }
#[derive(Debug)]
pub struct GradientPrimitiveCpu {
pub stops_range: ItemRange<GradientStop>,
pub stops_count: usize,
pub extend_mode: ExtendMode,
pub reverse_stops: bool,
pub gpu_blocks: [GpuBlockData; 3],
}
impl GradientPrimitiveCpu {
fn build_gpu_blocks_for_aligned(
&self,
display_list: &BuiltDisplayList,
mut request: GpuDataRequest,
) -> PrimitiveOpacity {
let mut opacity = PrimitiveOpacity::opaque();
request.extend_from_slice(&self.gpu_blocks);
let src_stops = display_list.get(self.stops_range);
for src in src_stops {
request.push(src.color.premultiplied());
request.push([src.offset, 0.0, 0.0, 0.0]);
opacity.accumulate(src.color.a);
}
opacity
}
fn build_gpu_blocks_for_angle_radial(
&self,
display_list: &BuiltDisplayList,
mut request: GpuDataRequest,
) {
request.extend_from_slice(&self.gpu_blocks);
let gradient_builder = GradientGpuBlockBuilder::new(self.stops_range, display_list);
gradient_builder.build(self.reverse_stops, &mut request);
}
}
// The gradient entry index for the first color stop // The gradient entry index for the first color stop
pub const GRADIENT_DATA_FIRST_STOP: usize = 0; pub const GRADIENT_DATA_FIRST_STOP: usize = 0;
// The gradient entry index for the last color stop // The gradient entry index for the last color stop
@ -670,7 +663,7 @@ impl TextRunPrimitiveCpu {
pub fn get_font( pub fn get_font(
&self, &self,
device_pixel_scale: DevicePixelScale, device_pixel_scale: DevicePixelScale,
transform: Option<&LayerToWorldTransform>, transform: Option<LayerToWorldTransform>,
) -> FontInstance { ) -> FontInstance {
let mut font = self.font.clone(); let mut font = self.font.clone();
font.size = font.size.scale_by(device_pixel_scale.0); font.size = font.size.scale_by(device_pixel_scale.0);
@ -678,7 +671,7 @@ impl TextRunPrimitiveCpu {
if transform.has_perspective_component() || !transform.has_2d_inverse() { if transform.has_perspective_component() || !transform.has_2d_inverse() {
font.render_mode = font.render_mode.limit_by(FontRenderMode::Alpha); font.render_mode = font.render_mode.limit_by(FontRenderMode::Alpha);
} else { } else {
font.transform = FontTransform::from(transform).quantize(); font.transform = FontTransform::from(&transform).quantize();
} }
} }
font font
@ -688,7 +681,7 @@ impl TextRunPrimitiveCpu {
&mut self, &mut self,
resource_cache: &mut ResourceCache, resource_cache: &mut ResourceCache,
device_pixel_scale: DevicePixelScale, device_pixel_scale: DevicePixelScale,
transform: Option<&LayerToWorldTransform>, transform: Option<LayerToWorldTransform>,
display_list: &BuiltDisplayList, display_list: &BuiltDisplayList,
gpu_cache: &mut GpuCache, gpu_cache: &mut GpuCache,
) { ) {
@ -937,8 +930,6 @@ pub enum PrimitiveContainer {
TextRun(TextRunPrimitiveCpu), TextRun(TextRunPrimitiveCpu),
Image(ImagePrimitiveCpu), Image(ImagePrimitiveCpu),
Border(BorderPrimitiveCpu), Border(BorderPrimitiveCpu),
AlignedGradient(GradientPrimitiveCpu),
AngleGradient(GradientPrimitiveCpu),
Picture(PicturePrimitive), Picture(PicturePrimitive),
Brush(BrushPrimitive), Brush(BrushPrimitive),
} }
@ -949,7 +940,6 @@ pub struct PrimitiveStore {
pub cpu_text_runs: Vec<TextRunPrimitiveCpu>, pub cpu_text_runs: Vec<TextRunPrimitiveCpu>,
pub cpu_pictures: Vec<PicturePrimitive>, pub cpu_pictures: Vec<PicturePrimitive>,
pub cpu_images: Vec<ImagePrimitiveCpu>, pub cpu_images: Vec<ImagePrimitiveCpu>,
pub cpu_gradients: Vec<GradientPrimitiveCpu>,
pub cpu_metadata: Vec<PrimitiveMetadata>, pub cpu_metadata: Vec<PrimitiveMetadata>,
pub cpu_borders: Vec<BorderPrimitiveCpu>, pub cpu_borders: Vec<BorderPrimitiveCpu>,
} }
@ -962,7 +952,6 @@ impl PrimitiveStore {
cpu_text_runs: Vec::new(), cpu_text_runs: Vec::new(),
cpu_pictures: Vec::new(), cpu_pictures: Vec::new(),
cpu_images: Vec::new(), cpu_images: Vec::new(),
cpu_gradients: Vec::new(),
cpu_borders: Vec::new(), cpu_borders: Vec::new(),
} }
} }
@ -974,7 +963,6 @@ impl PrimitiveStore {
cpu_text_runs: recycle_vec(self.cpu_text_runs), cpu_text_runs: recycle_vec(self.cpu_text_runs),
cpu_pictures: recycle_vec(self.cpu_pictures), cpu_pictures: recycle_vec(self.cpu_pictures),
cpu_images: recycle_vec(self.cpu_images), cpu_images: recycle_vec(self.cpu_images),
cpu_gradients: recycle_vec(self.cpu_gradients),
cpu_borders: recycle_vec(self.cpu_borders), cpu_borders: recycle_vec(self.cpu_borders),
} }
} }
@ -1015,6 +1003,7 @@ impl PrimitiveStore {
BrushKind::Image { .. } => PrimitiveOpacity::translucent(), BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(), BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(), BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
BrushKind::LinearGradient { .. } => PrimitiveOpacity::translucent(),
BrushKind::Picture => { BrushKind::Picture => {
// TODO(gw): This is not currently used. In the future // TODO(gw): This is not currently used. In the future
// we should detect opaque pictures. // we should detect opaque pictures.
@ -1077,29 +1066,6 @@ impl PrimitiveStore {
self.cpu_borders.push(border_cpu); self.cpu_borders.push(border_cpu);
metadata metadata
} }
PrimitiveContainer::AlignedGradient(gradient_cpu) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
prim_kind: PrimitiveKind::AlignedGradient,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()),
..base_metadata
};
self.cpu_gradients.push(gradient_cpu);
metadata
}
PrimitiveContainer::AngleGradient(gradient_cpu) => {
let metadata = PrimitiveMetadata {
// TODO: calculate if the gradient is actually opaque
opacity: PrimitiveOpacity::translucent(),
prim_kind: PrimitiveKind::AngleGradient,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()),
..base_metadata
};
self.cpu_gradients.push(gradient_cpu);
metadata
}
}; };
self.cpu_metadata.push(metadata); self.cpu_metadata.push(metadata);
@ -1146,7 +1112,7 @@ impl PrimitiveStore {
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0]; let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
// The transform only makes sense for screen space rasterization // The transform only makes sense for screen space rasterization
let transform = if pic_context.draw_text_transformed { let transform = if pic_context.draw_text_transformed {
Some(&prim_run_context.scroll_node.world_content_transform) Some(prim_run_context.scroll_node.world_content_transform.into())
} else { } else {
None None
}; };
@ -1304,7 +1270,8 @@ impl PrimitiveStore {
); );
} }
} }
BrushKind::RadialGradient { ref mut stops_handle, stops_range, .. } => { BrushKind::RadialGradient { gradient_index, stops_range, .. } => {
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) { if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
let gradient_builder = GradientGpuBlockBuilder::new( let gradient_builder = GradientGpuBlockBuilder::new(
stops_range, stops_range,
@ -1316,6 +1283,19 @@ impl PrimitiveStore {
); );
} }
} }
BrushKind::LinearGradient { gradient_index, stops_range, reverse_stops, .. } => {
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
let gradient_builder = GradientGpuBlockBuilder::new(
stops_range,
pic_context.display_list,
);
gradient_builder.build(
reverse_stops,
&mut request,
);
}
}
BrushKind::Mask { .. } | BrushKind::Mask { .. } |
BrushKind::Solid { .. } | BrushKind::Solid { .. } |
BrushKind::Clear | BrushKind::Clear |
@ -1323,8 +1303,6 @@ impl PrimitiveStore {
BrushKind::Picture { .. } => {} BrushKind::Picture { .. } => {}
} }
} }
PrimitiveKind::AlignedGradient |
PrimitiveKind::AngleGradient => {}
} }
// Mark this GPU resource as required for this frame. // Mark this GPU resource as required for this frame.
@ -1342,20 +1320,6 @@ impl PrimitiveStore {
let image = &self.cpu_images[metadata.cpu_prim_index.0]; let image = &self.cpu_images[metadata.cpu_prim_index.0];
image.write_gpu_blocks(request); image.write_gpu_blocks(request);
} }
PrimitiveKind::AlignedGradient => {
let gradient = &self.cpu_gradients[metadata.cpu_prim_index.0];
metadata.opacity = gradient.build_gpu_blocks_for_aligned(
pic_context.display_list,
request,
);
}
PrimitiveKind::AngleGradient => {
let gradient = &self.cpu_gradients[metadata.cpu_prim_index.0];
gradient.build_gpu_blocks_for_angle_radial(
pic_context.display_list,
request,
);
}
PrimitiveKind::TextRun => { PrimitiveKind::TextRun => {
let text = &self.cpu_text_runs[metadata.cpu_prim_index.0]; let text = &self.cpu_text_runs[metadata.cpu_prim_index.0];
text.write_gpu_blocks(&mut request); text.write_gpu_blocks(&mut request);
@ -1471,14 +1435,14 @@ impl PrimitiveStore {
let local_clip_rect = if clip_item.scroll_node_data_index == prim_run_context.scroll_node.node_data_index { let local_clip_rect = if clip_item.scroll_node_data_index == prim_run_context.scroll_node.node_data_index {
local_clip_rect local_clip_rect
} else { } else {
let clip_transform_data = &frame_context let clip_transform = frame_context
.node_data[clip_item.scroll_node_data_index.0 as usize]; .node_data[clip_item.scroll_node_data_index.0 as usize]
.transform;
let prim_transform = &prim_run_context.scroll_node.world_content_transform; let prim_transform = &prim_run_context.scroll_node.world_content_transform;
let relative_transform = prim_transform let relative_transform = prim_transform
.inverse() .inverse()
.unwrap_or(WorldToLayerTransform::identity()) .unwrap_or(WorldToLayerFastTransform::identity())
.pre_mul(&clip_transform_data.transform); .pre_mul(&clip_transform.into());
relative_transform.transform_rect(&local_clip_rect) relative_transform.transform_rect(&local_clip_rect)
}; };
@ -2061,8 +2025,7 @@ fn get_local_clip_rect_for_nodes(
); );
match local_rect { match local_rect {
Some(local_rect) => Some(local_rect) => scroll_node.coordinate_system_relative_transform.unapply(&local_rect),
Some(scroll_node.coordinate_system_relative_transform.unapply(&local_rect)),
None => None, None => None,
} }
} }

Просмотреть файл

@ -1007,6 +1007,9 @@ impl RenderBackend {
} }
}; };
let msg_update = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
self.result_tx.send(msg_update).unwrap();
let msg_publish = ResultMsg::PublishDocument( let msg_publish = ResultMsg::PublishDocument(
id, id,
render_doc, render_doc,

Просмотреть файл

@ -83,6 +83,10 @@ const GPU_CACHE_RESIZE_TEST: bool = false;
/// Number of GPU blocks per UV rectangle provided for an image. /// Number of GPU blocks per UV rectangle provided for an image.
pub const BLOCKS_PER_UV_RECT: usize = 2; pub const BLOCKS_PER_UV_RECT: usize = 2;
const GPU_TAG_BRUSH_LINEAR_GRADIENT: GpuProfileTag = GpuProfileTag {
label: "B_LinearGradient",
color: debug_colors::POWDERBLUE,
};
const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag { const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
label: "B_RadialGradient", label: "B_RadialGradient",
color: debug_colors::LIGHTPINK, color: debug_colors::LIGHTPINK,
@ -151,14 +155,6 @@ const GPU_TAG_PRIM_TEXT_RUN: GpuProfileTag = GpuProfileTag {
label: "TextRun", label: "TextRun",
color: debug_colors::BLUE, color: debug_colors::BLUE,
}; };
const GPU_TAG_PRIM_GRADIENT: GpuProfileTag = GpuProfileTag {
label: "Gradient",
color: debug_colors::YELLOW,
};
const GPU_TAG_PRIM_ANGLE_GRADIENT: GpuProfileTag = GpuProfileTag {
label: "AngleGradient",
color: debug_colors::POWDERBLUE,
};
const GPU_TAG_PRIM_BORDER_CORNER: GpuProfileTag = GpuProfileTag { const GPU_TAG_PRIM_BORDER_CORNER: GpuProfileTag = GpuProfileTag {
label: "BorderCorner", label: "BorderCorner",
color: debug_colors::DARKSLATEGREY, color: debug_colors::DARKSLATEGREY,
@ -200,8 +196,6 @@ impl TransformBatchKind {
ImageBufferKind::TextureExternal => "Image (External)", ImageBufferKind::TextureExternal => "Image (External)",
ImageBufferKind::Texture2DArray => "Image (Array)", ImageBufferKind::Texture2DArray => "Image (Array)",
}, },
TransformBatchKind::AlignedGradient => "AlignedGradient",
TransformBatchKind::AngleGradient => "AngleGradient",
TransformBatchKind::BorderCorner => "BorderCorner", TransformBatchKind::BorderCorner => "BorderCorner",
TransformBatchKind::BorderEdge => "BorderEdge", TransformBatchKind::BorderEdge => "BorderEdge",
} }
@ -213,8 +207,6 @@ impl TransformBatchKind {
TransformBatchKind::Image(..) => GPU_TAG_PRIM_IMAGE, TransformBatchKind::Image(..) => GPU_TAG_PRIM_IMAGE,
TransformBatchKind::BorderCorner => GPU_TAG_PRIM_BORDER_CORNER, TransformBatchKind::BorderCorner => GPU_TAG_PRIM_BORDER_CORNER,
TransformBatchKind::BorderEdge => GPU_TAG_PRIM_BORDER_EDGE, TransformBatchKind::BorderEdge => GPU_TAG_PRIM_BORDER_EDGE,
TransformBatchKind::AlignedGradient => GPU_TAG_PRIM_GRADIENT,
TransformBatchKind::AngleGradient => GPU_TAG_PRIM_ANGLE_GRADIENT,
} }
} }
} }
@ -235,6 +227,7 @@ impl BatchKind {
BrushBatchKind::MixBlend { .. } => "Brush (Composite)", BrushBatchKind::MixBlend { .. } => "Brush (Composite)",
BrushBatchKind::YuvImage(..) => "Brush (YuvImage)", BrushBatchKind::YuvImage(..) => "Brush (YuvImage)",
BrushBatchKind::RadialGradient => "Brush (RadialGradient)", BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
BrushBatchKind::LinearGradient => "Brush (LinearGradient)",
} }
} }
BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(), BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(),
@ -255,6 +248,7 @@ impl BatchKind {
BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND, BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE, BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT, BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
} }
} }
BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(), BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(),
@ -1618,6 +1612,7 @@ pub struct Renderer {
brush_mix_blend: BrushShader, brush_mix_blend: BrushShader,
brush_yuv_image: Vec<Option<BrushShader>>, brush_yuv_image: Vec<Option<BrushShader>>,
brush_radial_gradient: BrushShader, brush_radial_gradient: BrushShader,
brush_linear_gradient: BrushShader,
/// These are "cache clip shaders". These shaders are used to /// These are "cache clip shaders". These shaders are used to
/// draw clip instances into the cached clip mask. The results /// draw clip instances into the cached clip mask. The results
@ -1638,8 +1633,6 @@ pub struct Renderer {
ps_image: Vec<Option<PrimitiveShader>>, ps_image: Vec<Option<PrimitiveShader>>,
ps_border_corner: PrimitiveShader, ps_border_corner: PrimitiveShader,
ps_border_edge: PrimitiveShader, ps_border_edge: PrimitiveShader,
ps_gradient: PrimitiveShader,
ps_angle_gradient: PrimitiveShader,
ps_hw_composite: LazilyCompiledShader, ps_hw_composite: LazilyCompiledShader,
ps_split_composite: LazilyCompiledShader, ps_split_composite: LazilyCompiledShader,
@ -1884,6 +1877,17 @@ impl Renderer {
options.precache_shaders) options.precache_shaders)
}; };
let brush_linear_gradient = try!{
BrushShader::new("brush_linear_gradient",
&mut device,
if options.enable_dithering {
&dithering_feature
} else {
&[]
},
options.precache_shaders)
};
let cs_blur_a8 = try!{ let cs_blur_a8 = try!{
LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur), LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur),
"cs_blur", "cs_blur",
@ -2030,28 +2034,6 @@ impl Renderer {
options.precache_shaders) options.precache_shaders)
}; };
let ps_gradient = try!{
PrimitiveShader::new("ps_gradient",
&mut device,
if options.enable_dithering {
&dithering_feature
} else {
&[]
},
options.precache_shaders)
};
let ps_angle_gradient = try!{
PrimitiveShader::new("ps_angle_gradient",
&mut device,
if options.enable_dithering {
&dithering_feature
} else {
&[]
},
options.precache_shaders)
};
let ps_hw_composite = try!{ let ps_hw_composite = try!{
LazilyCompiledShader::new(ShaderKind::Primitive, LazilyCompiledShader::new(ShaderKind::Primitive,
"ps_hardware_composite", "ps_hardware_composite",
@ -2303,6 +2285,7 @@ impl Renderer {
brush_mix_blend, brush_mix_blend,
brush_yuv_image, brush_yuv_image,
brush_radial_gradient, brush_radial_gradient,
brush_linear_gradient,
cs_clip_rectangle, cs_clip_rectangle,
cs_clip_border, cs_clip_border,
cs_clip_image, cs_clip_image,
@ -2311,8 +2294,6 @@ impl Renderer {
ps_image, ps_image,
ps_border_corner, ps_border_corner,
ps_border_edge, ps_border_edge,
ps_gradient,
ps_angle_gradient,
ps_hw_composite, ps_hw_composite,
ps_split_composite, ps_split_composite,
debug: debug_renderer, debug: debug_renderer,
@ -2892,7 +2873,9 @@ impl Renderer {
for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents { for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents {
frame.profile_counters.reset_targets(); frame.profile_counters.reset_targets();
self.prepare_gpu_cache(frame); self.prepare_gpu_cache(frame);
assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id); assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id,
"Received frame depends on a later GPU cache epoch ({:?}) than one we received last via `UpdateGpuCache` ({:?})",
frame.gpu_cache_frame_id, self.gpu_cache_frame_id);
self.draw_tile_frame( self.draw_tile_frame(
frame, frame,
@ -3272,6 +3255,15 @@ impl Renderer {
&mut self.renderer_errors, &mut self.renderer_errors,
); );
} }
BrushBatchKind::LinearGradient => {
self.brush_linear_gradient.bind(
&mut self.device,
key.blend_mode,
projection,
0,
&mut self.renderer_errors,
);
}
BrushBatchKind::YuvImage(image_buffer_kind, format, color_space) => { BrushBatchKind::YuvImage(image_buffer_kind, format, color_space) => {
let shader_index = let shader_index =
Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space); Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space);
@ -3322,24 +3314,6 @@ impl Renderer {
&mut self.renderer_errors, &mut self.renderer_errors,
); );
} }
TransformBatchKind::AlignedGradient => {
self.ps_gradient.bind(
&mut self.device,
transform_kind,
projection,
0,
&mut self.renderer_errors,
);
}
TransformBatchKind::AngleGradient => {
self.ps_angle_gradient.bind(
&mut self.device,
transform_kind,
projection,
0,
&mut self.renderer_errors,
);
}
}, },
}; };
@ -4741,6 +4715,7 @@ impl Renderer {
self.brush_blend.deinit(&mut self.device); self.brush_blend.deinit(&mut self.device);
self.brush_mix_blend.deinit(&mut self.device); self.brush_mix_blend.deinit(&mut self.device);
self.brush_radial_gradient.deinit(&mut self.device); self.brush_radial_gradient.deinit(&mut self.device);
self.brush_linear_gradient.deinit(&mut self.device);
self.cs_clip_rectangle.deinit(&mut self.device); self.cs_clip_rectangle.deinit(&mut self.device);
self.cs_clip_image.deinit(&mut self.device); self.cs_clip_image.deinit(&mut self.device);
self.cs_clip_border.deinit(&mut self.device); self.cs_clip_border.deinit(&mut self.device);
@ -4766,8 +4741,6 @@ impl Renderer {
} }
self.ps_border_corner.deinit(&mut self.device); self.ps_border_corner.deinit(&mut self.device);
self.ps_border_edge.deinit(&mut self.device); self.ps_border_edge.deinit(&mut self.device);
self.ps_gradient.deinit(&mut self.device);
self.ps_angle_gradient.deinit(&mut self.device);
self.ps_hw_composite.deinit(&mut self.device); self.ps_hw_composite.deinit(&mut self.device);
self.ps_split_composite.deinit(&mut self.device); self.ps_split_composite.deinit(&mut self.device);
#[cfg(feature = "capture")] #[cfg(feature = "capture")]

Просмотреть файл

@ -16,7 +16,7 @@ use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex};
use gpu_types::{PrimitiveInstance}; use gpu_types::{PrimitiveInstance};
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture}; use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
use picture::{PictureKind}; use picture::{PictureKind};
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveStore}; use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveKind, PrimitiveStore};
use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask}; use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask};
use profiler::FrameProfileCounters; use profiler::FrameProfileCounters;
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind}; use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
@ -46,6 +46,7 @@ pub struct RenderTargetContext<'a> {
pub clip_scroll_tree: &'a ClipScrollTree, pub clip_scroll_tree: &'a ClipScrollTree,
pub use_dual_source_blending: bool, pub use_dual_source_blending: bool,
pub node_data: &'a [ClipScrollNodeData], pub node_data: &'a [ClipScrollNodeData],
pub cached_gradients: &'a [CachedGradient],
} }
#[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "capture", derive(Serialize))]
@ -599,6 +600,7 @@ impl RenderTarget for AlphaRenderTarget {
BrushKind::Line { .. } | BrushKind::Line { .. } |
BrushKind::YuvImage { .. } | BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } | BrushKind::RadialGradient { .. } |
BrushKind::LinearGradient { .. } |
BrushKind::Image { .. } => { BrushKind::Image { .. } => {
unreachable!("bug: unexpected brush here"); unreachable!("bug: unexpected brush here");
} }

Просмотреть файл

@ -3,10 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale}; use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
use api::{DevicePoint, DeviceRect, DeviceSize, LayerPoint, LayerRect, LayerSize}; use api::{DevicePoint, DeviceRect, DeviceSize, LayerPixel, LayerPoint, LayerRect, LayerSize};
use api::{LayerToWorldTransform, LayerTransform, LayerVector2D, WorldRect}; use api::{LayoutPixel, WorldPixel, WorldRect};
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, TypedTransform2D}; use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedPoint3D, TypedRect, TypedSize2D};
use euclid::TypedTransform3D; use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D};
use num_traits::Zero; use num_traits::Zero;
use std::{i32, f32}; use std::{i32, f32};
@ -22,6 +22,7 @@ pub trait MatrixHelpers<Src, Dst> {
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src>; fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src>;
fn transform_kind(&self) -> TransformedRectKind; fn transform_kind(&self) -> TransformedRectKind;
fn is_simple_translation(&self) -> bool; fn is_simple_translation(&self) -> bool;
fn is_simple_2d_translation(&self) -> bool;
} }
impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> { impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
@ -105,6 +106,14 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
self.m31.abs() < NEARLY_ZERO && self.m32.abs() < NEARLY_ZERO && self.m31.abs() < NEARLY_ZERO && self.m32.abs() < NEARLY_ZERO &&
self.m34.abs() < NEARLY_ZERO self.m34.abs() < NEARLY_ZERO
} }
fn is_simple_2d_translation(&self) -> bool {
if !self.is_simple_translation() {
return false;
}
self.m43.abs() < NEARLY_ZERO
}
} }
pub trait RectHelpers<U> pub trait RectHelpers<U>
@ -145,7 +154,7 @@ pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
} }
pub fn calculate_screen_bounding_rect( pub fn calculate_screen_bounding_rect(
transform: &LayerToWorldTransform, transform: &LayerToWorldFastTransform,
rect: &LayerRect, rect: &LayerRect,
device_pixel_scale: DevicePixelScale, device_pixel_scale: DevicePixelScale,
) -> DeviceIntRect { ) -> DeviceIntRect {
@ -334,67 +343,189 @@ impl MaxRect for DeviceRect {
/// An enum that tries to avoid expensive transformation matrix calculations /// An enum that tries to avoid expensive transformation matrix calculations
/// when possible when dealing with non-perspective axis-aligned transformations. /// when possible when dealing with non-perspective axis-aligned transformations.
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
pub enum TransformOrOffset { pub enum FastTransform<Src, Dst> {
/// A simple offset, which can be used without doing any matrix math. /// A simple offset, which can be used without doing any matrix math.
Offset(LayerVector2D), Offset(TypedVector2D<f32, Src>),
/// A transformation with an inverse. If the inverse isn't present, this isn't a 2D /// A 2D transformation with an inverse.
/// transformation, which means we need to fall back to using inverse_rect_footprint.
/// Since this operation is so expensive, we avoid it for the 2D case.
Transform { Transform {
transform: LayerTransform, transform: TypedTransform3D<f32, Src, Dst>,
inverse: Option<LayerTransform>, inverse: Option<TypedTransform3D<f32, Dst, Src>>,
} is_2d: bool,
},
} }
impl TransformOrOffset { impl<Src, Dst> FastTransform<Src, Dst> {
pub fn zero() -> TransformOrOffset { pub fn identity() -> Self {
TransformOrOffset::Offset(LayerVector2D::zero()) FastTransform::Offset(TypedVector2D::zero())
} }
fn new_transform(transform: LayerTransform) -> TransformOrOffset { pub fn with_vector(offset: TypedVector2D<f32, Src>) -> Self {
if transform.is_2d() { FastTransform::Offset(offset)
TransformOrOffset::Transform { }
transform,
inverse: Some(transform.inverse().expect("Expected invertible matrix.")) #[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 { #[inline(always)]
match *self { pub fn pre_translate(&self, other_offset: &TypedVector2D<f32, Src>) -> Self {
TransformOrOffset::Offset(offset) => rect.translate(&offset), match self {
TransformOrOffset::Transform {transform, .. } => transform.transform_rect(&rect), &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 { match *self {
TransformOrOffset::Offset(offset) => rect.translate(&-offset), FastTransform::Offset(..) => true,
TransformOrOffset::Transform { inverse: Some(inverse), .. } => FastTransform::Transform { ref transform, .. } =>
inverse.transform_rect(&rect), transform.preserves_2d_axis_alignment(),
TransformOrOffset::Transform { transform, inverse: None } =>
transform.inverse_rect_footprint(rect),
} }
} }
pub fn offset(&self, new_offset: LayerVector2D) -> TransformOrOffset { #[inline(always)]
pub fn has_perspective_component(&self) -> bool {
match *self { match *self {
TransformOrOffset::Offset(offset) => TransformOrOffset::Offset(offset + new_offset), FastTransform::Offset(..) => false,
TransformOrOffset::Transform { transform, .. } => { FastTransform::Transform { ref transform, .. } => transform.has_perspective_component(),
}
}
#[inline(always)]
pub fn is_backface_visible(&self) -> bool {
match *self {
FastTransform::Offset(..) => false,
FastTransform::Transform { ref transform, .. } => transform.is_backface_visible(),
}
}
#[inline(always)]
pub fn transform_point2d(&self, point: &TypedPoint2D<f32, Src>) -> TypedPoint2D<f32, Dst> {
match *self {
FastTransform::Offset(offset) => {
let new_point = *point + offset;
TypedPoint2D::from_untyped(&new_point.to_untyped())
}
FastTransform::Transform { ref transform, .. } => transform.transform_point2d(point),
}
}
#[inline(always)]
pub fn transform_point3d(&self, point: &TypedPoint3D<f32, Src>) -> TypedPoint3D<f32, Dst> {
match *self {
FastTransform::Offset(offset) =>
TypedPoint3D::new(point.x + offset.x, point.y + offset.y, point.z),
FastTransform::Transform { ref transform, .. } => transform.transform_point3d(point),
}
}
#[inline(always)]
pub fn transform_rect(&self, rect: &TypedRect<f32, Src>) -> TypedRect<f32, Dst> {
match *self {
FastTransform::Offset(offset) =>
TypedRect::from_untyped(&rect.to_untyped().translate(&offset.to_untyped())),
FastTransform::Transform { ref transform, .. } => transform.transform_rect(rect),
}
}
pub fn unapply(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>> {
match *self {
FastTransform::Offset(offset) =>
Some(TypedRect::from_untyped(&rect.to_untyped().translate(&-offset.to_untyped()))),
FastTransform::Transform { inverse: Some(ref inverse), is_2d: true, .. } =>
Some(inverse.transform_rect(&rect)),
FastTransform::Transform { ref transform, is_2d: false, .. } =>
Some(transform.inverse_rect_footprint(rect)),
FastTransform::Transform { inverse: None, .. } => None,
}
}
#[inline(always)]
pub fn offset(&self, new_offset: TypedVector2D<f32, Src>) -> Self {
match *self {
FastTransform::Offset(offset) => FastTransform::Offset(offset + new_offset),
FastTransform::Transform { ref transform, .. } => {
let transform = transform.pre_translate(new_offset.to_3d()); let transform = transform.pre_translate(new_offset.to_3d());
TransformOrOffset::new_transform(transform) FastTransform::with_transform(transform)
} }
} }
} }
pub fn update(&self, transform: LayerTransform) -> Option<TransformOrOffset> { pub fn post_translate(&self, new_offset: TypedVector2D<f32, Dst>) -> Self {
if transform.is_simple_translation() { match *self {
let offset = LayerVector2D::new(transform.m41, transform.m42); FastTransform::Offset(offset) => {
Some(self.offset(offset)) let offset = offset.to_untyped() + new_offset.to_untyped();
FastTransform::Offset(TypedVector2D::from_untyped(&offset))
}
FastTransform::Transform { ref transform, .. } => {
let transform = transform.post_translate(new_offset.to_3d());
FastTransform::with_transform(transform)
}
}
}
#[inline(always)]
pub fn inverse(&self) -> Option<FastTransform<Dst, Src>> {
match *self {
FastTransform::Offset(offset) =>
Some(FastTransform::Offset(TypedVector2D::new(-offset.x, -offset.y))),
FastTransform::Transform { transform, inverse: Some(inverse), is_2d, } =>
Some(FastTransform::Transform {
transform: inverse,
inverse: Some(transform),
is_2d
}),
FastTransform::Transform { inverse: None, .. } => None,
}
}
pub fn update(&self, transform: TypedTransform3D<f32, Src, Dst>) -> Option<Self> {
if transform.is_simple_2d_translation() {
Some(self.offset(TypedVector2D::new(transform.m41, transform.m42)))
} else { } else {
// If we break 2D axis alignment or have a perspective component, we need to start a // If we break 2D axis alignment or have a perspective component, we need to start a
// new incompatible coordinate system with which we cannot share clips without masking. // new incompatible coordinate system with which we cannot share clips without masking.
@ -402,3 +533,26 @@ impl TransformOrOffset {
} }
} }
} }
impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
fn from(transform: TypedTransform3D<f32, Src, Dst>) -> FastTransform<Src, Dst> {
FastTransform::with_transform(transform)
}
}
impl<Src, Dst> Into<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
fn into(self) -> TypedTransform3D<f32, Src, Dst> {
self.to_transform()
}
}
impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
fn from(vector: TypedVector2D<f32, Src>) -> FastTransform<Src, Dst> {
FastTransform::with_vector(vector)
}
}
pub type LayoutFastTransform = FastTransform<LayoutPixel, LayoutPixel>;
pub type LayerFastTransform = FastTransform<LayerPixel, LayerPixel>;
pub type LayerToWorldFastTransform = FastTransform<LayerPixel, WorldPixel>;
pub type WorldToLayerFastTransform = FastTransform<WorldPixel, LayerPixel>;

Просмотреть файл

@ -54,14 +54,6 @@ const SHADERS: &[Shader] = &[
name: "ps_border_edge", name: "ps_border_edge",
features: PRIM_FEATURES, features: PRIM_FEATURES,
}, },
Shader {
name: "ps_gradient",
features: PRIM_FEATURES,
},
Shader {
name: "ps_angle_gradient",
features: PRIM_FEATURES,
},
Shader { Shader {
name: "ps_hardware_composite", name: "ps_hardware_composite",
features: PRIM_FEATURES, features: PRIM_FEATURES,
@ -81,7 +73,7 @@ const SHADERS: &[Shader] = &[
// Brush shaders // Brush shaders
Shader { Shader {
name: "brush_yuv_image", name: "brush_yuv_image",
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED"], features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED", "YUV_NV12,TEXTURE_RECT"],
}, },
Shader { Shader {
name: "brush_mask", name: "brush_mask",
@ -109,6 +101,10 @@ const SHADERS: &[Shader] = &[
}, },
Shader { Shader {
name: "brush_radial_gradient", name: "brush_radial_gradient",
features: &[ "DITHERING" ],
},
Shader {
name: "brush_linear_gradient",
features: &[], features: &[],
}, },
]; ];

Просмотреть файл

@ -1 +1 @@
e8d2ffb404a85651fe08a6d09abbece9bd2b9182 8a19316a733a484bf9bafb8257e3008b1418bfe4