зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1438892 - Update webrender to e8d2ffb404a85651fe08a6d09abbece9bd2b9182. r=jrmuizel
MozReview-Commit-ID: hO7HCOnrIz --HG-- extra : rebase_source : e3da8bc05044ab29348c230be819467f90f581bd
This commit is contained in:
Родитель
7bff6906cb
Коммит
63b1e24e3d
|
@ -25,7 +25,7 @@ lazy_static = "1"
|
|||
log = "0.4"
|
||||
num-traits = "0.1.32"
|
||||
time = "0.1"
|
||||
rayon = "0.8"
|
||||
rayon = "1"
|
||||
webrender_api = {path = "../webrender_api"}
|
||||
bitflags = "1.0"
|
||||
thread_profiler = "0.1.1"
|
||||
|
|
|
@ -11,7 +11,7 @@ extern crate webrender;
|
|||
mod boilerplate;
|
||||
|
||||
use boilerplate::{Example, HandyDandyRectBuilder};
|
||||
use rayon::{Configuration as ThreadPoolConfig, ThreadPool};
|
||||
use rayon::{ThreadPool, ThreadPoolBuilder};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::sync::Arc;
|
||||
|
@ -282,10 +282,11 @@ impl Example for App {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let worker_config =
|
||||
ThreadPoolConfig::new().thread_name(|idx| format!("WebRender:Worker#{}", idx));
|
||||
let workers =
|
||||
ThreadPoolBuilder::new().thread_name(|idx| format!("WebRender:Worker#{}", idx))
|
||||
.build();
|
||||
|
||||
let workers = Arc::new(ThreadPool::new(worker_config).unwrap());
|
||||
let workers = Arc::new(workers.unwrap());
|
||||
|
||||
let opts = webrender::RendererOptions {
|
||||
workers: Some(Arc::clone(&workers)),
|
||||
|
|
|
@ -15,6 +15,8 @@ void brush_vs(
|
|||
#define VECS_PER_BRUSH_PRIM 2
|
||||
#define VECS_PER_SEGMENT 2
|
||||
|
||||
#define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION 1
|
||||
|
||||
struct BrushInstance {
|
||||
int picture_address;
|
||||
int prim_address;
|
||||
|
@ -24,6 +26,7 @@ struct BrushInstance {
|
|||
int z;
|
||||
int segment_index;
|
||||
int edge_mask;
|
||||
int flags;
|
||||
ivec3 user_data;
|
||||
};
|
||||
|
||||
|
@ -37,7 +40,8 @@ BrushInstance load_brush() {
|
|||
bi.scroll_node_id = aData0.z & 0xffff;
|
||||
bi.z = aData0.w;
|
||||
bi.segment_index = aData1.x & 0xffff;
|
||||
bi.edge_mask = aData1.x >> 16;
|
||||
bi.edge_mask = (aData1.x >> 16) & 0xff;
|
||||
bi.flags = (aData1.x >> 24);
|
||||
bi.user_data = aData1.yzw;
|
||||
|
||||
return bi;
|
||||
|
@ -135,6 +139,8 @@ void main(void) {
|
|||
#endif
|
||||
} else {
|
||||
bvec4 edge_mask = notEqual(brush.edge_mask & ivec4(1, 2, 4, 8), ivec4(0));
|
||||
bool do_perspective_interpolation = (brush.flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0;
|
||||
|
||||
vi = write_transform_vertex(
|
||||
local_segment_rect,
|
||||
brush_prim.local_rect,
|
||||
|
@ -142,7 +148,8 @@ void main(void) {
|
|||
mix(vec4(0.0), vec4(1.0), edge_mask),
|
||||
float(brush.z),
|
||||
scroll_node,
|
||||
pic_task
|
||||
pic_task,
|
||||
do_perspective_interpolation
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#define VECS_PER_SPECIFIC_BRUSH 5
|
||||
#define FORCE_NO_PERSPECTIVE
|
||||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
varying vec3 vUv;
|
||||
varying float vW;
|
||||
|
||||
flat varying float vAmount;
|
||||
flat varying int vOp;
|
||||
|
@ -25,10 +25,9 @@ void brush_vs(
|
|||
) {
|
||||
PictureTask src_task = fetch_picture_task(user_data.x);
|
||||
vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
|
||||
vec2 uv = (vi.snapped_device_pos +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin) * vi.w;
|
||||
vW = vi.w;
|
||||
vec2 uv = vi.snapped_device_pos +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vUv = vec3(uv / texture_size, src_task.common_data.texture_layer_index);
|
||||
|
||||
vOp = user_data.y;
|
||||
|
@ -115,8 +114,7 @@ vec4 Opacity(vec4 Cs, float amount) {
|
|||
}
|
||||
|
||||
vec4 brush_fs() {
|
||||
vec2 uv = vUv.xy / vW;
|
||||
vec4 Cs = texture(sColor0, vec3(uv, vUv.z));
|
||||
vec4 Cs = texture(sColor0, vUv);
|
||||
|
||||
// Un-premultiply the input.
|
||||
Cs.rgb /= Cs.a;
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
varying vec3 vUv;
|
||||
varying float vW;
|
||||
|
||||
varying vec3 vSrcUv;
|
||||
varying vec3 vBackdropUv;
|
||||
flat varying int vOp;
|
||||
|
@ -24,18 +21,17 @@ void brush_vs(
|
|||
) {
|
||||
vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
|
||||
vOp = user_data.x;
|
||||
vW = vi.w;
|
||||
|
||||
PictureTask src_task = fetch_picture_task(user_data.z);
|
||||
vec2 src_uv = (vi.snapped_device_pos +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin) * vi.w;
|
||||
vec2 src_uv = vi.snapped_device_pos +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vSrcUv = vec3(src_uv / texture_size, src_task.common_data.texture_layer_index);
|
||||
|
||||
RenderTaskCommonData backdrop_task = fetch_render_task_common_data(user_data.y);
|
||||
vec2 backdrop_uv = (vi.snapped_device_pos +
|
||||
backdrop_task.task_rect.p0 -
|
||||
src_task.content_origin) * vi.w;
|
||||
vec2 backdrop_uv = vi.snapped_device_pos +
|
||||
backdrop_task.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vBackdropUv = vec3(backdrop_uv / texture_size, backdrop_task.texture_layer_index);
|
||||
}
|
||||
#endif
|
||||
|
@ -205,10 +201,8 @@ const int MixBlendMode_Color = 14;
|
|||
const int MixBlendMode_Luminosity = 15;
|
||||
|
||||
vec4 brush_fs() {
|
||||
vec2 uv = vUv.xy / vW;
|
||||
|
||||
vec4 Cb = texture(sCacheRGBA8, vBackdropUv);
|
||||
vec4 Cs = texture(sCacheRGBA8, vSrcUv);
|
||||
vec4 Cb = textureLod(sCacheRGBA8, vBackdropUv, 0.0);
|
||||
vec4 Cs = textureLod(sCacheRGBA8, vSrcUv, 0.0);
|
||||
|
||||
if (Cb.a == 0.0) {
|
||||
return Cs;
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
* 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
|
||||
#define VECS_PER_SPECIFIC_BRUSH 2
|
||||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
flat varying int vGradientAddress;
|
||||
flat varying float vGradientRepeat;
|
||||
|
@ -12,24 +14,34 @@ flat varying vec2 vEndCenter;
|
|||
flat varying float vStartRadius;
|
||||
flat varying float vEndRadius;
|
||||
|
||||
flat varying vec2 vTileSize;
|
||||
flat varying vec2 vTileRepeat;
|
||||
|
||||
varying vec2 vPos;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
varying vec2 vLocalPos;
|
||||
#endif
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
void main(void) {
|
||||
Primitive prim = load_primitive();
|
||||
RadialGradient gradient = fetch_radial_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);
|
||||
struct RadialGradient {
|
||||
vec4 start_end_center;
|
||||
vec4 start_end_radius_ratio_xy_extend_mode;
|
||||
};
|
||||
|
||||
vPos = vi.local_pos - prim.local_rect.p0;
|
||||
RadialGradient fetch_radial_gradient(int address) {
|
||||
vec4 data[2] = fetch_from_resource_cache_2(address);
|
||||
return RadialGradient(data[0], data[1]);
|
||||
}
|
||||
|
||||
void brush_vs(
|
||||
VertexInfo vi,
|
||||
int prim_address,
|
||||
RectWithSize local_rect,
|
||||
ivec3 user_data,
|
||||
PictureTask pic_task
|
||||
) {
|
||||
RadialGradient gradient = fetch_radial_gradient(prim_address);
|
||||
|
||||
vPos = vi.local_pos - local_rect.p0;
|
||||
|
||||
vStartCenter = gradient.start_end_center.xy;
|
||||
vEndCenter = gradient.start_end_center.zw;
|
||||
|
@ -37,38 +49,28 @@ void main(void) {
|
|||
vStartRadius = gradient.start_end_radius_ratio_xy_extend_mode.x;
|
||||
vEndRadius = gradient.start_end_radius_ratio_xy_extend_mode.y;
|
||||
|
||||
vTileSize = gradient.tile_size_repeat.xy;
|
||||
vTileRepeat = gradient.tile_size_repeat.zw;
|
||||
|
||||
// Transform all coordinates by the y scale so the
|
||||
// fragment shader can work with circles
|
||||
float ratio_xy = gradient.start_end_radius_ratio_xy_extend_mode.z;
|
||||
vPos.y *= ratio_xy;
|
||||
vStartCenter.y *= ratio_xy;
|
||||
vEndCenter.y *= ratio_xy;
|
||||
vTileSize.y *= ratio_xy;
|
||||
vTileRepeat.y *= ratio_xy;
|
||||
|
||||
vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
|
||||
vGradientAddress = user_data.x;
|
||||
|
||||
// Whether to repeat the gradient instead of clamping.
|
||||
vGradientRepeat = float(int(gradient.start_end_radius_ratio_xy_extend_mode.w) != EXTEND_MODE_CLAMP);
|
||||
|
||||
write_clip(vi.screen_pos, prim.clip_area);
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
vLocalPos = vi.local_pos;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
void main(void) {
|
||||
vec2 pos = mod(vPos, vTileRepeat);
|
||||
|
||||
if (pos.x >= vTileSize.x ||
|
||||
pos.y >= vTileSize.y) {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 brush_fs() {
|
||||
vec2 cd = vEndCenter - vStartCenter;
|
||||
vec2 pd = pos - vStartCenter;
|
||||
vec2 pd = vPos - vStartCenter;
|
||||
float rd = vEndRadius - vStartRadius;
|
||||
|
||||
// Solve for t in length(t * cd - pd) = vStartRadius + t * rd
|
||||
|
@ -110,6 +112,10 @@ void main(void) {
|
|||
offset,
|
||||
vGradientRepeat);
|
||||
|
||||
oFragColor = color * do_clip();
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
color *= init_transform_fs(vLocalPos);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,166 @@
|
|||
/* 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 0
|
||||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
// TODO(gw): Consider whether we should even have separate shader compilations
|
||||
// for the various YUV modes. To save on the number of shaders we
|
||||
// need to compile, it might be worth just doing this as an
|
||||
// uber-shader instead.
|
||||
// TODO(gw): Regardless of the above, we should remove the separate shader
|
||||
// compilations for the different color space matrix below. That
|
||||
// can be provided by a branch in the VS and pushed through the
|
||||
// interpolators, or even as a uniform that breaks batches, rather
|
||||
// that needing to compile to / select a different shader when
|
||||
// there is a different color space.
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
varying vec2 vLocalPos;
|
||||
#endif
|
||||
|
||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||
varying vec3 vUv_Y;
|
||||
flat varying vec4 vUvBounds_Y;
|
||||
|
||||
varying vec3 vUv_U;
|
||||
flat varying vec4 vUvBounds_U;
|
||||
|
||||
varying vec3 vUv_V;
|
||||
flat varying vec4 vUvBounds_V;
|
||||
#elif defined (WR_FEATURE_YUV_NV12)
|
||||
varying vec3 vUv_Y;
|
||||
flat varying vec4 vUvBounds_Y;
|
||||
|
||||
varying vec3 vUv_UV;
|
||||
flat varying vec4 vUvBounds_UV;
|
||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||
varying vec3 vUv_YUV;
|
||||
flat varying vec4 vUvBounds_YUV;
|
||||
#endif
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
void write_uv_rect(
|
||||
int resource_id,
|
||||
vec2 f,
|
||||
vec2 texture_size,
|
||||
out vec3 uv,
|
||||
out vec4 uv_bounds
|
||||
) {
|
||||
ImageResource res = fetch_image_resource(resource_id);
|
||||
vec2 uv0 = res.uv_rect.p0;
|
||||
vec2 uv1 = res.uv_rect.p1;
|
||||
|
||||
uv.xy = mix(uv0, uv1, f);
|
||||
uv.z = res.layer;
|
||||
|
||||
uv_bounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5));
|
||||
|
||||
#ifndef WR_FEATURE_TEXTURE_RECT
|
||||
uv.xy /= texture_size;
|
||||
uv_bounds /= texture_size.xyxy;
|
||||
#endif
|
||||
}
|
||||
|
||||
void brush_vs(
|
||||
VertexInfo vi,
|
||||
int prim_address,
|
||||
RectWithSize local_rect,
|
||||
ivec3 user_data,
|
||||
PictureTask pic_task
|
||||
) {
|
||||
vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
vLocalPos = vi.local_pos;
|
||||
#endif
|
||||
|
||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, vec2(textureSize(sColor1, 0).xy), vUv_U, vUvBounds_U);
|
||||
write_uv_rect(user_data.z, f, vec2(textureSize(sColor2, 0).xy), vUv_V, vUvBounds_V);
|
||||
#elif defined (WR_FEATURE_YUV_NV12)
|
||||
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, vec2(textureSize(sColor1, 0).xy), vUv_UV, vUvBounds_UV);
|
||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||
write_uv_rect(user_data.x, f, vec2(textureSize(sColor0, 0).xy), vUv_YUV, vUvBounds_YUV);
|
||||
#endif //WR_FEATURE_YUV_*
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
#if !defined(WR_FEATURE_YUV_REC601) && !defined(WR_FEATURE_YUV_REC709)
|
||||
#define WR_FEATURE_YUV_REC601
|
||||
#endif
|
||||
|
||||
// The constants added to the Y, U and V components are applied in the fragment shader.
|
||||
#if defined(WR_FEATURE_YUV_REC601)
|
||||
// From Rec601:
|
||||
// [R] [1.1643835616438356, 0.0, 1.5960267857142858 ] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255].
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrix = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0, -0.39176, 2.01723,
|
||||
1.59603, -0.81297, 0.0
|
||||
);
|
||||
#elif defined(WR_FEATURE_YUV_REC709)
|
||||
// From Rec709:
|
||||
// [R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.1124017857142854, 0.0 ] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255]:
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrix = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0 , -0.21325, 2.11240,
|
||||
1.79274, -0.53291, 0.0
|
||||
);
|
||||
#endif
|
||||
|
||||
vec4 brush_fs() {
|
||||
vec3 yuv_value;
|
||||
|
||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||
// The yuv_planar format should have this third texture coordinate.
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
vec2 uv_u = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
|
||||
vec2 uv_v = clamp(vUv_V.xy, vUvBounds_V.xy, vUvBounds_V.zw);
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
|
||||
yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, vUv_U.z)).r;
|
||||
yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, vUv_V.z)).r;
|
||||
#elif defined (WR_FEATURE_YUV_NV12)
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
vec2 uv_uv = clamp(vUv_UV.xy, vUvBounds_UV.xy, vUvBounds_UV.zw);
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
|
||||
yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, vUv_UV.z)).rg;
|
||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||
// "The Y, Cb and Cr color channels within the 422 data are mapped into
|
||||
// the existing green, blue and red color channels."
|
||||
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
|
||||
vec2 uv_y = clamp(vUv_YUV.xy, vUvBounds_YUV.xy, vUvBounds_YUV.zw);
|
||||
yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_YUV.z)).gbr;
|
||||
#else
|
||||
yuv_value = vec3(0.0);
|
||||
#endif
|
||||
|
||||
// See the YuvColorMatrix definition for an explanation of where the constants come from.
|
||||
vec3 rgb = YuvColorMatrix * (yuv_value - vec3(0.06275, 0.50196, 0.50196));
|
||||
vec4 color = vec4(rgb, 1.0);
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
color *= init_transform_fs(vLocalPos);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif
|
|
@ -4,73 +4,31 @@
|
|||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
// One iteration of Newton's method on the 2D equation of an ellipse:
|
||||
//
|
||||
// Signed distance to an ellipse.
|
||||
// Taken from http://www.iquilezles.org/www/articles/ellipsedist/ellipsedist.htm
|
||||
// Note that this fails for exact circles.
|
||||
// E(x, y) = x^2/a^2 + y^2/b^2 - 1
|
||||
//
|
||||
float sdEllipse( vec2 p, in vec2 ab ) {
|
||||
p = abs( p ); if( p.x > p.y ){ p=p.yx; ab=ab.yx; }
|
||||
float l = ab.y*ab.y - ab.x*ab.x;
|
||||
|
||||
float m = ab.x*p.x/l;
|
||||
float n = ab.y*p.y/l;
|
||||
float m2 = m*m;
|
||||
float n2 = n*n;
|
||||
|
||||
float c = (m2 + n2 - 1.0)/3.0;
|
||||
float c3 = c*c*c;
|
||||
|
||||
float q = c3 + m2*n2*2.0;
|
||||
float d = c3 + m2*n2;
|
||||
float g = m + m*n2;
|
||||
|
||||
float co;
|
||||
|
||||
if( d<0.0 )
|
||||
{
|
||||
float p = acos(q/c3)/3.0;
|
||||
float s = cos(p);
|
||||
float t = sin(p)*sqrt(3.0);
|
||||
float rx = sqrt( -c*(s + t + 2.0) + m2 );
|
||||
float ry = sqrt( -c*(s - t + 2.0) + m2 );
|
||||
co = ( ry + sign(l)*rx + abs(g)/(rx*ry) - m)/2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
float h = 2.0*m*n*sqrt( d );
|
||||
float s = sign(q+h)*pow( abs(q+h), 1.0/3.0 );
|
||||
float u = sign(q-h)*pow( abs(q-h), 1.0/3.0 );
|
||||
float rx = -s - u - c*4.0 + 2.0*m2;
|
||||
float ry = (s - u)*sqrt(3.0);
|
||||
float rm = sqrt( rx*rx + ry*ry );
|
||||
float p = ry/sqrt(rm-rx);
|
||||
co = (p + 2.0*g/rm - m)/2.0;
|
||||
}
|
||||
|
||||
float si = sqrt( 1.0 - co*co );
|
||||
|
||||
vec2 r = vec2( ab.x*co, ab.y*si );
|
||||
|
||||
return length(r - p ) * sign(p.y-r.y);
|
||||
}
|
||||
|
||||
// The Jacobian of this equation is:
|
||||
//
|
||||
// J(E(x, y)) = [ 2*x/a^2 2*y/b^2 ]
|
||||
//
|
||||
// We approximate the distance with:
|
||||
//
|
||||
// E(x, y) / ||J(E(x, y))||
|
||||
//
|
||||
// See G. Taubin, "Distance Approximations for Rasterizing Implicit
|
||||
// Curves", section 3.
|
||||
float distance_to_ellipse(vec2 p, vec2 radii, float aa_range) {
|
||||
// sdEllipse fails on exact circles, so handle equal
|
||||
// radii here. The branch coherency should make this
|
||||
// a performance win for the circle case too.
|
||||
float len = length(p);
|
||||
if (radii.x == radii.y) {
|
||||
return len - radii.x;
|
||||
float dist;
|
||||
if (any(lessThanEqual(radii, vec2(0.0)))) {
|
||||
dist = length(p);
|
||||
} else {
|
||||
if (len < min(radii.x, radii.y) - aa_range) {
|
||||
return -aa_range;
|
||||
} else if (len > max(radii.x, radii.y) + aa_range) {
|
||||
return aa_range;
|
||||
}
|
||||
|
||||
return sdEllipse(p, radii);
|
||||
vec2 invRadiiSq = 1.0 / (radii * radii);
|
||||
float g = dot(p * p * invRadiiSq, vec2(1.0)) - 1.0;
|
||||
vec2 dG = 2.0 * p * invRadiiSq;
|
||||
dist = g * inversesqrt(dot(dG, dG));
|
||||
}
|
||||
return clamp(dist, -aa_range, aa_range);
|
||||
}
|
||||
|
||||
float clip_against_ellipse_if_needed(
|
||||
|
|
|
@ -315,27 +315,6 @@ Gradient fetch_gradient(int address) {
|
|||
return Gradient(data[0], data[1], data[2]);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
struct RadialGradient {
|
||||
vec4 start_end_center;
|
||||
vec4 start_end_radius_ratio_xy_extend_mode;
|
||||
vec4 tile_size_repeat;
|
||||
};
|
||||
|
||||
RadialGradient fetch_radial_gradient(int address) {
|
||||
vec4 data[3] = fetch_from_resource_cache_3(address);
|
||||
return RadialGradient(data[0], data[1], data[2]);
|
||||
}
|
||||
|
||||
struct Glyph {
|
||||
vec2 offset;
|
||||
};
|
||||
|
@ -624,7 +603,8 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
|
|||
vec4 clip_edge_mask,
|
||||
float z,
|
||||
ClipScrollNode scroll_node,
|
||||
PictureTask task) {
|
||||
PictureTask task,
|
||||
bool do_perspective_interpolation) {
|
||||
// Calculate a clip rect from local_rect + local clip
|
||||
RectWithEndpoint clip_rect = to_rect_with_endpoint(local_clip_rect);
|
||||
RectWithEndpoint segment_rect = to_rect_with_endpoint(local_segment_rect);
|
||||
|
@ -661,13 +641,16 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
|
|||
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
|
||||
vec2 task_offset = task.common_data.task_rect.p0 - task.content_origin;
|
||||
|
||||
// Force w = 1, if we don't want perspective interpolation (for
|
||||
// example, drawing a screen-space quad on an element with a
|
||||
// perspective transform).
|
||||
world_pos.w = mix(1.0, world_pos.w, do_perspective_interpolation);
|
||||
|
||||
// We want the world space coords to be perspective divided by W.
|
||||
// We also want that to apply to any interpolators. However, we
|
||||
// want a constant Z across the primitive, since we're using it
|
||||
// for draw ordering - so scale by the W coord to ensure this.
|
||||
vec4 final_pos = vec4((device_pos + task_offset) * world_pos.w,
|
||||
z * world_pos.w,
|
||||
world_pos.w);
|
||||
vec4 final_pos = vec4(device_pos + task_offset, z, 1.0) * world_pos.w;
|
||||
gl_Position = uTransform * final_pos;
|
||||
|
||||
vLocalBounds = mix(
|
||||
|
@ -694,7 +677,8 @@ VertexInfo write_transform_vertex_primitive(Primitive prim) {
|
|||
vec4(1.0),
|
||||
prim.z,
|
||||
prim.scroll_node,
|
||||
prim.task
|
||||
prim.task,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -320,7 +320,8 @@ void main(void) {
|
|||
edge_mask,
|
||||
prim.z,
|
||||
prim.scroll_node,
|
||||
prim.task);
|
||||
prim.task,
|
||||
true);
|
||||
#else
|
||||
VertexInfo vi = write_vertex(segment_rect,
|
||||
prim.local_clip_rect,
|
||||
|
|
|
@ -233,7 +233,8 @@ void main(void) {
|
|||
edge_mask,
|
||||
prim.z,
|
||||
prim.scroll_node,
|
||||
prim.task);
|
||||
prim.task,
|
||||
true);
|
||||
#else
|
||||
VertexInfo vi = write_vertex(segment_rect,
|
||||
prim.local_clip_rect,
|
||||
|
|
|
@ -9,6 +9,16 @@ 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);
|
||||
|
@ -73,7 +83,8 @@ void main(void) {
|
|||
vec4(1.0),
|
||||
prim.z,
|
||||
prim.scroll_node,
|
||||
prim.task);
|
||||
prim.task,
|
||||
true);
|
||||
vLocalPos = vi.local_pos;
|
||||
vec2 f = (vi.local_pos.xy - prim.local_rect.p0) / prim.local_rect.size;
|
||||
#else
|
||||
|
|
|
@ -1,197 +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
|
||||
|
||||
// If this is in WR_FEATURE_TEXTURE_RECT mode, the rect and size use non-normalized
|
||||
// texture coordinates. Otherwise, it uses normalized texture coordinates. Please
|
||||
// check GL_TEXTURE_RECTANGLE.
|
||||
flat varying vec2 vTextureOffsetY; // Offset of the y plane into the texture atlas.
|
||||
flat varying vec2 vTextureOffsetU; // Offset of the u plane into the texture atlas.
|
||||
flat varying vec2 vTextureOffsetV; // Offset of the v plane into the texture atlas.
|
||||
flat varying vec2 vTextureSizeY; // Size of the y plane in the texture atlas.
|
||||
flat varying vec2 vTextureSizeUv; // Size of the u and v planes in the texture atlas.
|
||||
flat varying vec2 vStretchSize;
|
||||
flat varying vec2 vHalfTexelY; // Normalized length of the half of a Y texel.
|
||||
flat varying vec2 vHalfTexelUv; // Normalized length of the half of u and v texels.
|
||||
flat varying vec3 vLayers;
|
||||
|
||||
#ifdef WR_FEATURE_TRANSFORM
|
||||
flat varying vec4 vLocalRect;
|
||||
#endif
|
||||
|
||||
varying vec2 vLocalPos;
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
struct YuvImage {
|
||||
vec2 size;
|
||||
};
|
||||
|
||||
YuvImage fetch_yuv_image(int address) {
|
||||
vec4 data = fetch_from_resource_cache_1(address);
|
||||
return YuvImage(data.xy);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
Primitive prim = load_primitive();
|
||||
#ifdef WR_FEATURE_TRANSFORM
|
||||
VertexInfo vi = write_transform_vertex_primitive(prim);
|
||||
vLocalPos = vi.local_pos;
|
||||
vLocalRect = vec4(prim.local_rect.p0, prim.local_rect.p0 + prim.local_rect.size);
|
||||
#else
|
||||
VertexInfo vi = write_vertex(prim.local_rect,
|
||||
prim.local_clip_rect,
|
||||
prim.z,
|
||||
prim.scroll_node,
|
||||
prim.task,
|
||||
prim.local_rect);
|
||||
vLocalPos = vi.local_pos - prim.local_rect.p0;
|
||||
#endif
|
||||
|
||||
write_clip(vi.screen_pos, prim.clip_area);
|
||||
|
||||
ImageResource y_rect = fetch_image_resource(prim.user_data0);
|
||||
vLayers = vec3(y_rect.layer, 0.0, 0.0);
|
||||
|
||||
#ifndef WR_FEATURE_INTERLEAVED_Y_CB_CR // only 1 channel
|
||||
ImageResource u_rect = fetch_image_resource(prim.user_data1);
|
||||
vLayers.y = u_rect.layer;
|
||||
#ifndef WR_FEATURE_NV12 // 2 channel
|
||||
ImageResource v_rect = fetch_image_resource(prim.user_data2);
|
||||
vLayers.z = v_rect.layer;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If this is in WR_FEATURE_TEXTURE_RECT mode, the rect and size use
|
||||
// non-normalized texture coordinates.
|
||||
#ifdef WR_FEATURE_TEXTURE_RECT
|
||||
vec2 y_texture_size_normalization_factor = vec2(1, 1);
|
||||
#else
|
||||
vec2 y_texture_size_normalization_factor = vec2(textureSize(sColor0, 0));
|
||||
#endif
|
||||
vec2 y_st0 = y_rect.uv_rect.p0 / y_texture_size_normalization_factor;
|
||||
vec2 y_st1 = y_rect.uv_rect.p1 / y_texture_size_normalization_factor;
|
||||
|
||||
vTextureSizeY = y_st1 - y_st0;
|
||||
vTextureOffsetY = y_st0;
|
||||
|
||||
#ifndef WR_FEATURE_INTERLEAVED_Y_CB_CR
|
||||
// This assumes the U and V surfaces have the same size.
|
||||
#ifdef WR_FEATURE_TEXTURE_RECT
|
||||
vec2 uv_texture_size_normalization_factor = vec2(1, 1);
|
||||
#else
|
||||
vec2 uv_texture_size_normalization_factor = vec2(textureSize(sColor1, 0));
|
||||
#endif
|
||||
vec2 u_st0 = u_rect.uv_rect.p0 / uv_texture_size_normalization_factor;
|
||||
vec2 u_st1 = u_rect.uv_rect.p1 / uv_texture_size_normalization_factor;
|
||||
|
||||
#ifndef WR_FEATURE_NV12
|
||||
vec2 v_st0 = v_rect.uv_rect.p0 / uv_texture_size_normalization_factor;
|
||||
#endif
|
||||
|
||||
vTextureSizeUv = u_st1 - u_st0;
|
||||
vTextureOffsetU = u_st0;
|
||||
#ifndef WR_FEATURE_NV12
|
||||
vTextureOffsetV = v_st0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
YuvImage image = fetch_yuv_image(prim.specific_prim_address);
|
||||
vStretchSize = image.size;
|
||||
|
||||
vHalfTexelY = vec2(0.5) / y_texture_size_normalization_factor;
|
||||
#ifndef WR_FEATURE_INTERLEAVED_Y_CB_CR
|
||||
vHalfTexelUv = vec2(0.5) / uv_texture_size_normalization_factor;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
#if !defined(WR_FEATURE_YUV_REC601) && !defined(WR_FEATURE_YUV_REC709)
|
||||
#define WR_FEATURE_YUV_REC601
|
||||
#endif
|
||||
|
||||
// The constants added to the Y, U and V components are applied in the fragment shader.
|
||||
#if defined(WR_FEATURE_YUV_REC601)
|
||||
// From Rec601:
|
||||
// [R] [1.1643835616438356, 0.0, 1.5960267857142858 ] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255].
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrix = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0, -0.39176, 2.01723,
|
||||
1.59603, -0.81297, 0.0
|
||||
);
|
||||
#elif defined(WR_FEATURE_YUV_REC709)
|
||||
// From Rec709:
|
||||
// [R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.1124017857142854, 0.0 ] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255]:
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrix = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0 , -0.21325, 2.11240,
|
||||
1.79274, -0.53291, 0.0
|
||||
);
|
||||
#endif
|
||||
|
||||
void main(void) {
|
||||
#ifdef WR_FEATURE_TRANSFORM
|
||||
float alpha = init_transform_fs(vLocalPos);
|
||||
|
||||
// We clamp the texture coordinate calculation here to the local rectangle boundaries,
|
||||
// which makes the edge of the texture stretch instead of repeat.
|
||||
vec2 relative_pos_in_rect = clamp(vLocalPos, vLocalRect.xy, vLocalRect.zw) - vLocalRect.xy;
|
||||
#else
|
||||
float alpha = 1.0;;
|
||||
vec2 relative_pos_in_rect = vLocalPos;
|
||||
#endif
|
||||
|
||||
alpha *= do_clip();
|
||||
|
||||
// We clamp the texture coordinates to the half-pixel offset from the borders
|
||||
// in order to avoid sampling outside of the texture area.
|
||||
vec2 st_y = vTextureOffsetY + clamp(
|
||||
relative_pos_in_rect / vStretchSize * vTextureSizeY,
|
||||
vHalfTexelY, vTextureSizeY - vHalfTexelY);
|
||||
#ifndef WR_FEATURE_INTERLEAVED_Y_CB_CR
|
||||
vec2 uv_offset = clamp(
|
||||
relative_pos_in_rect / vStretchSize * vTextureSizeUv,
|
||||
vHalfTexelUv, vTextureSizeUv - vHalfTexelUv);
|
||||
// NV12 only uses 2 textures. The sColor0 is for y and sColor1 is for uv.
|
||||
// The texture coordinates of u and v are the same. So, we could skip the
|
||||
// st_v if the format is NV12.
|
||||
vec2 st_u = vTextureOffsetU + uv_offset;
|
||||
#endif
|
||||
|
||||
vec3 yuv_value;
|
||||
#ifdef WR_FEATURE_INTERLEAVED_Y_CB_CR
|
||||
// "The Y, Cb and Cr color channels within the 422 data are mapped into
|
||||
// the existing green, blue and red color channels."
|
||||
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
|
||||
yuv_value = TEX_SAMPLE(sColor0, vec3(st_y, vLayers.x)).gbr;
|
||||
#elif defined(WR_FEATURE_NV12)
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(st_y, vLayers.x)).r;
|
||||
yuv_value.yz = TEX_SAMPLE(sColor1, vec3(st_u, vLayers.y)).rg;
|
||||
#else
|
||||
// The yuv_planar format should have this third texture coordinate.
|
||||
vec2 st_v = vTextureOffsetV + uv_offset;
|
||||
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(st_y, vLayers.x)).r;
|
||||
yuv_value.y = TEX_SAMPLE(sColor1, vec3(st_u, vLayers.y)).r;
|
||||
yuv_value.z = TEX_SAMPLE(sColor2, vec3(st_v, vLayers.z)).r;
|
||||
#endif
|
||||
|
||||
// See the YuvColorMatrix definition for an explanation of where the constants come from.
|
||||
vec3 rgb = YuvColorMatrix * (yuv_value - vec3(0.06275, 0.50196, 0.50196));
|
||||
oFragColor = vec4(rgb * alpha, alpha);
|
||||
}
|
||||
#endif
|
|
@ -7,22 +7,20 @@ use api::{DeviceUintRect, DeviceUintPoint, DeviceUintSize, ExternalImageType, Fi
|
|||
use api::{DeviceIntPoint, LayerPoint, SubpixelDirection, YuvColorSpace, YuvFormat};
|
||||
use api::{LayerToWorldTransform, WorldPixel};
|
||||
use border::{BorderCornerInstance, BorderCornerSide, BorderEdgeKind};
|
||||
use clip::{ClipSource, ClipStore};
|
||||
use clip::{ClipSource, ClipStore, ClipWorkItem};
|
||||
use clip_scroll_tree::{CoordinateSystemId};
|
||||
use euclid::{TypedTransform3D, vec3};
|
||||
use glyph_rasterizer::GlyphFormat;
|
||||
use gpu_cache::{GpuCache, GpuCacheAddress};
|
||||
use gpu_types::{BrushImageKind, BrushInstance, ClipChainRectIndex};
|
||||
use gpu_types::{BrushFlags, BrushImageKind, BrushInstance, ClipChainRectIndex};
|
||||
use gpu_types::{ClipMaskInstance, ClipScrollNodeIndex};
|
||||
use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveInstance};
|
||||
use internal_types::{FastHashMap, SourceTexture};
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
||||
use plane_split::{BspSplitter, Polygon, Splitter};
|
||||
use prim_store::{ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
|
||||
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
|
||||
use render_task::{ClipWorkItem};
|
||||
use render_task::{RenderTaskAddress, RenderTaskId};
|
||||
use render_task::{RenderTaskKind, RenderTaskTree};
|
||||
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
|
||||
use renderer::{BlendMode, ImageBufferKind};
|
||||
use renderer::BLOCKS_PER_UV_RECT;
|
||||
use resource_cache::{CacheItem, GlyphFetchResult, ImageRequest, ResourceCache};
|
||||
|
@ -40,10 +38,8 @@ const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fff);
|
|||
pub enum TransformBatchKind {
|
||||
TextRun(GlyphFormat),
|
||||
Image(ImageBufferKind),
|
||||
YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace),
|
||||
AlignedGradient,
|
||||
AngleGradient,
|
||||
RadialGradient,
|
||||
BorderCorner,
|
||||
BorderEdge,
|
||||
}
|
||||
|
@ -80,6 +76,8 @@ pub enum BrushBatchKind {
|
|||
source_id: RenderTaskId,
|
||||
backdrop_id: RenderTaskId,
|
||||
},
|
||||
YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace),
|
||||
RadialGradient,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
|
@ -953,6 +951,7 @@ impl AlphaBatchBuilder {
|
|||
z,
|
||||
segment_index: 0,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
user_data: [
|
||||
cache_task_address.0 as i32,
|
||||
BrushImageKind::Simple as i32,
|
||||
|
@ -1039,6 +1038,7 @@ impl AlphaBatchBuilder {
|
|||
z,
|
||||
segment_index: 0,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
user_data: [
|
||||
cache_task_address.0 as i32,
|
||||
BrushImageKind::Simple as i32,
|
||||
|
@ -1052,12 +1052,12 @@ impl AlphaBatchBuilder {
|
|||
}
|
||||
|
||||
let secondary_id = secondary_render_task_id.expect("no secondary!?");
|
||||
let render_task = &render_tasks[secondary_id];
|
||||
let saved_index = render_tasks[secondary_id].saved_index.expect("no saved index!?");
|
||||
debug_assert_ne!(saved_index, SavedTargetIndex::PENDING);
|
||||
let secondary_task_address = render_tasks.get_task_address(secondary_id);
|
||||
let render_pass_index = render_task.pass_index.expect("no render_pass_index!?");
|
||||
let secondary_textures = BatchTextures {
|
||||
colors: [
|
||||
SourceTexture::RenderTaskCacheRGBA8(render_pass_index),
|
||||
SourceTexture::RenderTaskCache(saved_index),
|
||||
SourceTexture::Invalid,
|
||||
SourceTexture::Invalid,
|
||||
],
|
||||
|
@ -1116,6 +1116,7 @@ impl AlphaBatchBuilder {
|
|||
z,
|
||||
segment_index: 0,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
user_data: [
|
||||
cache_task_address.0 as i32,
|
||||
filter_mode,
|
||||
|
@ -1155,6 +1156,7 @@ impl AlphaBatchBuilder {
|
|||
z,
|
||||
segment_index: 0,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
user_data: [
|
||||
mode as u32 as i32,
|
||||
backdrop_task_address.0 as i32,
|
||||
|
@ -1226,73 +1228,6 @@ impl AlphaBatchBuilder {
|
|||
let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
|
||||
batch.push(base_instance.build(0, 0, 0));
|
||||
}
|
||||
PrimitiveKind::RadialGradient => {
|
||||
let kind = BatchKind::Transformable(
|
||||
transform_kind,
|
||||
TransformBatchKind::RadialGradient,
|
||||
);
|
||||
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));
|
||||
}
|
||||
PrimitiveKind::YuvImage => {
|
||||
let mut textures = BatchTextures::no_texture();
|
||||
let mut uv_rect_addresses = [0; 3];
|
||||
let image_yuv_cpu =
|
||||
&ctx.prim_store.cpu_yuv_images[prim_metadata.cpu_prim_index.0];
|
||||
|
||||
//yuv channel
|
||||
let channel_count = image_yuv_cpu.format.get_plane_num();
|
||||
debug_assert!(channel_count <= 3);
|
||||
for channel in 0 .. channel_count {
|
||||
let image_key = image_yuv_cpu.yuv_key[channel];
|
||||
|
||||
let cache_item = resolve_image(
|
||||
ImageRequest {
|
||||
key: image_key,
|
||||
rendering: image_yuv_cpu.image_rendering,
|
||||
tile: None,
|
||||
},
|
||||
ctx.resource_cache,
|
||||
gpu_cache,
|
||||
deferred_resolves,
|
||||
);
|
||||
|
||||
if cache_item.texture_id == SourceTexture::Invalid {
|
||||
warn!("Warnings: skip a PrimitiveKind::YuvImage");
|
||||
debug!("at {:?}.", task_relative_bounding_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
textures.colors[channel] = cache_item.texture_id;
|
||||
uv_rect_addresses[channel] = cache_item.uv_rect_handle.as_int(gpu_cache);
|
||||
}
|
||||
|
||||
// All yuv textures should be the same type.
|
||||
let buffer_kind = get_buffer_kind(textures.colors[0]);
|
||||
assert!(
|
||||
textures.colors[1 .. image_yuv_cpu.format.get_plane_num()]
|
||||
.iter()
|
||||
.all(|&tid| buffer_kind == get_buffer_kind(tid))
|
||||
);
|
||||
|
||||
let kind = BatchKind::Transformable(
|
||||
transform_kind,
|
||||
TransformBatchKind::YuvImage(
|
||||
buffer_kind,
|
||||
image_yuv_cpu.format,
|
||||
image_yuv_cpu.color_space,
|
||||
),
|
||||
);
|
||||
let key = BatchKey::new(kind, non_segmented_blend_mode, textures);
|
||||
let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect);
|
||||
|
||||
batch.push(base_instance.build(
|
||||
uv_rect_addresses[0],
|
||||
uv_rect_addresses[1],
|
||||
uv_rect_addresses[2],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1324,6 +1259,7 @@ impl AlphaBatchBuilder {
|
|||
z,
|
||||
segment_index: 0,
|
||||
edge_flags: EdgeAaSegmentMask::all(),
|
||||
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
user_data,
|
||||
};
|
||||
|
||||
|
@ -1440,6 +1376,71 @@ impl BrushPrimitive {
|
|||
[0; 3],
|
||||
))
|
||||
}
|
||||
BrushKind::RadialGradient { ref stops_handle, .. } => {
|
||||
Some((
|
||||
BrushBatchKind::RadialGradient,
|
||||
BatchTextures::no_texture(),
|
||||
[
|
||||
stops_handle.as_int(gpu_cache),
|
||||
0,
|
||||
0,
|
||||
],
|
||||
))
|
||||
}
|
||||
BrushKind::YuvImage { format, yuv_key, image_rendering, color_space } => {
|
||||
let mut textures = BatchTextures::no_texture();
|
||||
let mut uv_rect_addresses = [0; 3];
|
||||
|
||||
//yuv channel
|
||||
let channel_count = format.get_plane_num();
|
||||
debug_assert!(channel_count <= 3);
|
||||
for channel in 0 .. channel_count {
|
||||
let image_key = yuv_key[channel];
|
||||
|
||||
let cache_item = resolve_image(
|
||||
ImageRequest {
|
||||
key: image_key,
|
||||
rendering: image_rendering,
|
||||
tile: None,
|
||||
},
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
deferred_resolves,
|
||||
);
|
||||
|
||||
if cache_item.texture_id == SourceTexture::Invalid {
|
||||
warn!("Warnings: skip a PrimitiveKind::YuvImage");
|
||||
return None;
|
||||
}
|
||||
|
||||
textures.colors[channel] = cache_item.texture_id;
|
||||
uv_rect_addresses[channel] = cache_item.uv_rect_handle.as_int(gpu_cache);
|
||||
}
|
||||
|
||||
// All yuv textures should be the same type.
|
||||
let buffer_kind = get_buffer_kind(textures.colors[0]);
|
||||
assert!(
|
||||
textures.colors[1 .. format.get_plane_num()]
|
||||
.iter()
|
||||
.all(|&tid| buffer_kind == get_buffer_kind(tid))
|
||||
);
|
||||
|
||||
let kind = BrushBatchKind::YuvImage(
|
||||
buffer_kind,
|
||||
format,
|
||||
color_space,
|
||||
);
|
||||
|
||||
Some((
|
||||
kind,
|
||||
textures,
|
||||
[
|
||||
uv_rect_addresses[0],
|
||||
uv_rect_addresses[1],
|
||||
uv_rect_addresses[2],
|
||||
],
|
||||
))
|
||||
}
|
||||
BrushKind::Mask { .. } => {
|
||||
unreachable!("bug: mask brushes not expected in normal alpha pass");
|
||||
}
|
||||
|
@ -1463,10 +1464,8 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
}
|
||||
|
||||
PrimitiveKind::Border |
|
||||
PrimitiveKind::YuvImage |
|
||||
PrimitiveKind::AlignedGradient |
|
||||
PrimitiveKind::AngleGradient |
|
||||
PrimitiveKind::RadialGradient |
|
||||
PrimitiveKind::Picture => {
|
||||
BlendMode::PremultipliedAlpha
|
||||
}
|
||||
|
@ -1486,6 +1485,8 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
|||
BrushKind::Solid { .. } |
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Line { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::Picture => {
|
||||
BlendMode::PremultipliedAlpha
|
||||
}
|
||||
|
|
|
@ -2,15 +2,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF};
|
||||
use api::{LayerPoint, LayerRect, LayerPrimitiveInfo, LayerSize};
|
||||
use api::{NormalBorder, RepeatMode, TexelRect};
|
||||
use api::{BorderRadius, BorderSide, BorderStyle, BorderWidths, ColorF, LayerPoint};
|
||||
use api::{LayerPrimitiveInfo, LayerRect, LayerSize, NormalBorder, RepeatMode, TexelRect};
|
||||
use clip::ClipSource;
|
||||
use ellipse::Ellipse;
|
||||
use frame_builder::FrameBuilder;
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use prim_store::{BorderPrimitiveCpu, BrushSegment, BrushSegmentDescriptor};
|
||||
use prim_store::{BrushClipMaskKind, EdgeAaSegmentMask, PrimitiveContainer};
|
||||
use prim_store::{BorderPrimitiveCpu, BrushClipMaskKind, BrushSegment, BrushSegmentDescriptor};
|
||||
use prim_store::{EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain};
|
||||
use util::{lerp, pack_as_float};
|
||||
|
||||
#[repr(u8)]
|
||||
|
@ -286,7 +285,7 @@ impl FrameBuilder {
|
|||
info: &LayerPrimitiveInfo,
|
||||
border: &NormalBorder,
|
||||
widths: &BorderWidths,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
corner_instances: [BorderCornerInstance; 4],
|
||||
edges: [BorderEdgeKind; 4],
|
||||
clip_sources: Vec<ClipSource>,
|
||||
|
@ -354,7 +353,7 @@ impl FrameBuilder {
|
|||
info: &LayerPrimitiveInfo,
|
||||
border: &NormalBorder,
|
||||
widths: &BorderWidths,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
) {
|
||||
// The border shader is quite expensive. For simple borders, we can just draw
|
||||
// the border with a few rectangles. This generally gives better batching, and
|
||||
|
|
|
@ -2,16 +2,15 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ColorF, LayerPoint, LayerRect, LayerSize, LayerVector2D};
|
||||
use api::{BorderRadius, BoxShadowClipMode, LayoutSize, LayerPrimitiveInfo};
|
||||
use api::{ClipMode, ClipAndScrollInfo, ComplexClipRegion, LocalClip};
|
||||
use api::{PipelineId};
|
||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion, LayerPoint};
|
||||
use api::{LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D, LayoutSize, LocalClip};
|
||||
use api::PipelineId;
|
||||
use app_units::Au;
|
||||
use clip::ClipSource;
|
||||
use frame_builder::FrameBuilder;
|
||||
use gpu_types::BrushImageKind;
|
||||
use prim_store::{PrimitiveContainer};
|
||||
use prim_store::{BrushMaskKind, BrushKind, BrushPrimitive};
|
||||
use prim_store::{BrushKind, BrushMaskKind, BrushPrimitive, PrimitiveContainer};
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use picture::PicturePrimitive;
|
||||
use util::RectHelpers;
|
||||
use render_task::MAX_BLUR_STD_DEVIATION;
|
||||
|
@ -53,7 +52,7 @@ impl FrameBuilder {
|
|||
pub fn add_box_shadow(
|
||||
&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
prim_info: &LayerPrimitiveInfo,
|
||||
box_offset: &LayerVector2D,
|
||||
color: &ColorF,
|
||||
|
@ -88,7 +87,8 @@ impl FrameBuilder {
|
|||
if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 {
|
||||
return;
|
||||
}
|
||||
let mut clips = Vec::new();
|
||||
let mut clips = Vec::with_capacity(2);
|
||||
clips.push(ClipSource::Rectangle(*prim_info.local_clip.clip_rect()));
|
||||
|
||||
let fast_info = match clip_mode {
|
||||
BoxShadowClipMode::Outset => {
|
||||
|
@ -264,8 +264,10 @@ impl FrameBuilder {
|
|||
border_radius,
|
||||
ClipMode::ClipOut,
|
||||
));
|
||||
|
||||
let pic_info = LayerPrimitiveInfo::new(pic_rect);
|
||||
let pic_info = LayerPrimitiveInfo::with_clip_rect(
|
||||
pic_rect,
|
||||
*prim_info.local_clip.clip_rect()
|
||||
);
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&pic_info,
|
||||
|
@ -332,6 +334,12 @@ impl FrameBuilder {
|
|||
clip_and_scroll
|
||||
);
|
||||
|
||||
let clip_rect = prim_info.local_clip.clip_rect();
|
||||
let clip_rect = match prim_info.rect.intersection(clip_rect) {
|
||||
Some(clip_rect) => clip_rect,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Draw the picture one pixel outside the original
|
||||
// rect to account for the inflate above. This
|
||||
// extra edge will be clipped by the local clip
|
||||
|
@ -339,7 +347,7 @@ impl FrameBuilder {
|
|||
let pic_rect = prim_info.rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
|
||||
let pic_info = LayerPrimitiveInfo::with_clip_rect(
|
||||
pic_rect,
|
||||
prim_info.rect
|
||||
clip_rect
|
||||
);
|
||||
|
||||
// Add a normal clip to ensure nothing gets drawn
|
||||
|
|
|
@ -6,12 +6,15 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS
|
|||
use api::{ImageRendering, LayerRect, LayerToWorldTransform, LayoutPoint, LayoutVector2D};
|
||||
use api::LocalClip;
|
||||
use border::{BorderCornerClipSource, ensure_no_corner_overlap};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||
use ellipse::Ellipse;
|
||||
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
|
||||
use gpu_types::ClipScrollNodeIndex;
|
||||
use prim_store::{ClipData, ImageMaskData};
|
||||
use resource_cache::{ImageRequest, ResourceCache};
|
||||
use util::{MaxRect, MatrixHelpers, calculate_screen_bounding_rect, extract_inner_rect_safe};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type ClipStore = FreeList<ClipSources>;
|
||||
pub type ClipSourcesHandle = FreeListHandle<ClipSources>;
|
||||
|
@ -349,3 +352,106 @@ pub fn rounded_rectangle_contains_point(point: &LayoutPoint,
|
|||
|
||||
true
|
||||
}
|
||||
|
||||
pub type ClipChainNodeRef = Option<Rc<ClipChainNode>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClipChainNode {
|
||||
pub work_item: ClipWorkItem,
|
||||
pub local_clip_rect: LayerRect,
|
||||
pub screen_outer_rect: DeviceIntRect,
|
||||
pub screen_inner_rect: DeviceIntRect,
|
||||
pub prev: ClipChainNodeRef,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClipChain {
|
||||
pub parent_index: Option<ClipChainIndex>,
|
||||
pub combined_outer_screen_rect: DeviceIntRect,
|
||||
pub combined_inner_screen_rect: DeviceIntRect,
|
||||
pub nodes: ClipChainNodeRef,
|
||||
}
|
||||
|
||||
impl ClipChain {
|
||||
pub fn empty(screen_rect: &DeviceIntRect) -> ClipChain {
|
||||
ClipChain {
|
||||
parent_index: None,
|
||||
combined_inner_screen_rect: *screen_rect,
|
||||
combined_outer_screen_rect: *screen_rect,
|
||||
nodes: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_added_node(
|
||||
&self,
|
||||
work_item: ClipWorkItem,
|
||||
local_clip_rect: LayerRect,
|
||||
screen_outer_rect: DeviceIntRect,
|
||||
screen_inner_rect: DeviceIntRect,
|
||||
) -> ClipChain {
|
||||
// If the new node's inner rectangle completely surrounds our outer rectangle,
|
||||
// we can discard the new node entirely since it isn't going to affect anything.
|
||||
if screen_inner_rect.contains_rect(&self.combined_outer_screen_rect) {
|
||||
return self.clone();
|
||||
}
|
||||
|
||||
let new_node = ClipChainNode {
|
||||
work_item,
|
||||
local_clip_rect,
|
||||
screen_outer_rect,
|
||||
screen_inner_rect,
|
||||
prev: None,
|
||||
};
|
||||
|
||||
let mut new_chain = self.clone();
|
||||
new_chain.add_node(new_node);
|
||||
new_chain
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, mut new_node: ClipChainNode) {
|
||||
new_node.prev = self.nodes.clone();
|
||||
|
||||
// If this clip's outer rectangle is completely enclosed by the clip
|
||||
// chain's inner rectangle, then the only clip that matters from this point
|
||||
// on is this clip. We can disconnect this clip from the parent clip chain.
|
||||
if self.combined_inner_screen_rect.contains_rect(&new_node.screen_outer_rect) {
|
||||
new_node.prev = None;
|
||||
}
|
||||
|
||||
self.combined_outer_screen_rect =
|
||||
self.combined_outer_screen_rect.intersection(&new_node.screen_outer_rect)
|
||||
.unwrap_or_else(DeviceIntRect::zero);
|
||||
self.combined_inner_screen_rect =
|
||||
self.combined_inner_screen_rect.intersection(&new_node.screen_inner_rect)
|
||||
.unwrap_or_else(DeviceIntRect::zero);
|
||||
|
||||
self.nodes = Some(Rc::new(new_node));
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipChainNodeIter {
|
||||
pub current: ClipChainNodeRef,
|
||||
}
|
||||
|
||||
impl Iterator for ClipChainNodeIter {
|
||||
type Item = Rc<ClipChainNode>;
|
||||
|
||||
fn next(&mut self) -> ClipChainNodeRef {
|
||||
let previous = self.current.clone();
|
||||
self.current = match self.current {
|
||||
Some(ref item) => item.prev.clone(),
|
||||
None => return None,
|
||||
};
|
||||
previous
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ClipWorkItem {
|
||||
pub scroll_node_data_index: ClipScrollNodeIndex,
|
||||
pub clip_sources: ClipSourcesWeakHandle,
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, LayerRect};
|
||||
use api::{LayerSize, LayerToWorldTransform, LayerTransform, LayerVector2D, LayoutTransform};
|
||||
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollEventPhase};
|
||||
use api::{ScrollLocation, ScrollNodeIdType, ScrollSensitivity, StickyOffsetBounds, WorldPoint};
|
||||
use clip::{ClipSourcesHandle, ClipStore};
|
||||
use clip_scroll_tree::{CoordinateSystemId, TransformUpdateState};
|
||||
use api::{ScrollLocation, ScrollSensitivity, StickyOffsetBounds, WorldPoint};
|
||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState};
|
||||
use euclid::SideOffsets2D;
|
||||
use geometry::ray_intersects_rect;
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData};
|
||||
use render_task::{ClipChain, ClipWorkItem};
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use spring::{DAMPING, STIFFNESS, Spring};
|
||||
|
@ -56,7 +55,10 @@ pub enum NodeType {
|
|||
ReferenceFrame(ReferenceFrameInfo),
|
||||
|
||||
/// Other nodes just do clipping, but no transformation.
|
||||
Clip(ClipSourcesHandle),
|
||||
Clip {
|
||||
handle: ClipSourcesHandle,
|
||||
clip_chain_index: ClipChainIndex
|
||||
},
|
||||
|
||||
/// Transforms it's content, but doesn't clip it. Can also be adjusted
|
||||
/// by scroll events or setting scroll offsets.
|
||||
|
@ -106,9 +108,6 @@ pub struct ClipScrollNode {
|
|||
/// The type of this node and any data associated with that node type.
|
||||
pub node_type: NodeType,
|
||||
|
||||
/// The ClipChain that will be used if this node is used as the 'clipping node.'
|
||||
pub clip_chain: Option<ClipChain>,
|
||||
|
||||
/// True if this node is transformed by an invertible transform. If not, display items
|
||||
/// transformed by this node will not be displayed and display items not transformed by this
|
||||
/// node will not be clipped by clips that are transformed by this node.
|
||||
|
@ -128,7 +127,7 @@ pub struct ClipScrollNode {
|
|||
}
|
||||
|
||||
impl ClipScrollNode {
|
||||
fn new(
|
||||
pub fn new(
|
||||
pipeline_id: PipelineId,
|
||||
parent_id: Option<ClipId>,
|
||||
rect: &LayerRect,
|
||||
|
@ -142,7 +141,6 @@ impl ClipScrollNode {
|
|||
children: Vec::new(),
|
||||
pipeline_id,
|
||||
node_type: node_type,
|
||||
clip_chain: None,
|
||||
invertible: true,
|
||||
coordinate_system_id: CoordinateSystemId(0),
|
||||
coordinate_system_relative_transform: TransformOrOffset::zero(),
|
||||
|
@ -170,15 +168,6 @@ impl ClipScrollNode {
|
|||
Self::new(pipeline_id, Some(parent_id), frame_rect, node_type)
|
||||
}
|
||||
|
||||
pub fn new_clip_node(
|
||||
pipeline_id: PipelineId,
|
||||
parent_id: ClipId,
|
||||
handle: ClipSourcesHandle,
|
||||
clip_rect: LayerRect,
|
||||
) -> Self {
|
||||
Self::new(pipeline_id, Some(parent_id), &clip_rect, NodeType::Clip(handle))
|
||||
}
|
||||
|
||||
pub fn new_reference_frame(
|
||||
parent_id: Option<ClipId>,
|
||||
frame_rect: &LayerRect,
|
||||
|
@ -271,7 +260,6 @@ impl ClipScrollNode {
|
|||
self.invertible = false;
|
||||
self.world_content_transform = LayerToWorldTransform::identity();
|
||||
self.world_viewport_transform = LayerToWorldTransform::identity();
|
||||
self.clip_chain = None;
|
||||
}
|
||||
|
||||
pub fn push_gpu_node_data(&mut self, node_data: &mut Vec<ClipScrollNodeData>) {
|
||||
|
@ -304,6 +292,7 @@ impl ClipScrollNode {
|
|||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
scene_properties: &SceneProperties,
|
||||
clip_chains: &mut Vec<ClipChain>,
|
||||
) {
|
||||
// If any of our parents was not rendered, we are not rendered either and can just
|
||||
// quit here.
|
||||
|
@ -331,6 +320,7 @@ impl ClipScrollNode {
|
|||
clip_store,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
clip_chains,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -341,11 +331,11 @@ impl ClipScrollNode {
|
|||
clip_store: &mut ClipStore,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
clip_chains: &mut Vec<ClipChain>,
|
||||
) {
|
||||
let clip_sources_handle = match self.node_type {
|
||||
NodeType::Clip(ref handle) => handle,
|
||||
let (clip_sources_handle, clip_chain_index) = match self.node_type {
|
||||
NodeType::Clip { ref handle, clip_chain_index } => (handle, clip_chain_index),
|
||||
_ => {
|
||||
self.clip_chain = Some(state.parent_clip_chain.clone());
|
||||
self.invertible = true;
|
||||
return;
|
||||
}
|
||||
|
@ -364,29 +354,22 @@ impl ClipScrollNode {
|
|||
"Clipping node didn't have outer rect."
|
||||
);
|
||||
|
||||
// If this clip's inner rectangle completely surrounds the existing clip
|
||||
// chain's outer rectangle, we can discard this clip entirely since it isn't
|
||||
// going to affect anything.
|
||||
if screen_inner_rect.contains_rect(&state.parent_clip_chain.combined_outer_screen_rect) {
|
||||
self.clip_chain = Some(state.parent_clip_chain.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
let work_item = ClipWorkItem {
|
||||
scroll_node_data_index: self.node_data_index,
|
||||
clip_sources: clip_sources_handle.weak(),
|
||||
coordinate_system_id: state.current_coordinate_system_id,
|
||||
};
|
||||
|
||||
let clip_chain = state.parent_clip_chain.new_with_added_node(
|
||||
let mut clip_chain = clip_chains[state.parent_clip_chain_index.0].new_with_added_node(
|
||||
work_item,
|
||||
self.coordinate_system_relative_transform.apply(&local_outer_rect),
|
||||
screen_outer_rect,
|
||||
screen_inner_rect,
|
||||
);
|
||||
|
||||
self.clip_chain = Some(clip_chain.clone());
|
||||
state.parent_clip_chain = clip_chain;
|
||||
clip_chain.parent_index = Some(state.parent_clip_chain_index);
|
||||
clip_chains[clip_chain_index.0] = clip_chain;
|
||||
state.parent_clip_chain_index = clip_chain_index;
|
||||
}
|
||||
|
||||
pub fn update_transform(
|
||||
|
@ -621,7 +604,7 @@ impl ClipScrollNode {
|
|||
state.nearest_scrolling_ancestor_viewport
|
||||
.translate(&translation);
|
||||
}
|
||||
NodeType::Clip(..) => { }
|
||||
NodeType::Clip{ .. } => { }
|
||||
NodeType::ScrollFrame(ref scrolling) => {
|
||||
state.parent_accumulated_scroll_offset =
|
||||
scrolling.offset + state.parent_accumulated_scroll_offset;
|
||||
|
@ -768,12 +751,7 @@ impl ClipScrollNode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn matches_id(&self, node_id: ClipId, id_to_match: ScrollNodeIdType) -> bool {
|
||||
let external_id = match id_to_match {
|
||||
ScrollNodeIdType::ExternalScrollId(id) => id,
|
||||
ScrollNodeIdType::ClipId(clip_id) => return node_id == clip_id,
|
||||
};
|
||||
|
||||
pub fn matches_external_id(&self, external_id: ExternalScrollId) -> bool {
|
||||
match self.node_type {
|
||||
NodeType::ScrollFrame(info) if info.external_id == Some(external_id) => true,
|
||||
_ => false,
|
||||
|
|
|
@ -2,17 +2,15 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ClipChainId, ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint};
|
||||
use api::{LayerRect, LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping};
|
||||
use api::{ScrollEventPhase, ScrollLocation, ScrollNodeIdType};
|
||||
use api::{ScrollNodeState, WorldPoint};
|
||||
use clip::ClipStore;
|
||||
use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect};
|
||||
use api::{LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase};
|
||||
use api::{ScrollLocation, ScrollNodeState, WorldPoint};
|
||||
use clip::{ClipChain, ClipSourcesHandle, ClipStore};
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo};
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData};
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use print_tree::{PrintTree, PrintTreePrinter};
|
||||
use render_task::ClipChain;
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::SceneProperties;
|
||||
use util::TransformOrOffset;
|
||||
|
@ -44,11 +42,14 @@ impl CoordinateSystemId {
|
|||
}
|
||||
|
||||
pub struct ClipChainDescriptor {
|
||||
pub id: ClipChainId,
|
||||
pub parent: Option<ClipChainId>,
|
||||
pub index: ClipChainIndex,
|
||||
pub parent: Option<ClipChainIndex>,
|
||||
pub clips: Vec<ClipId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ClipChainIndex(pub usize);
|
||||
|
||||
pub struct ClipScrollTree {
|
||||
pub nodes: FastHashMap<ClipId, ClipScrollNode>,
|
||||
|
||||
|
@ -57,10 +58,11 @@ pub struct ClipScrollTree {
|
|||
/// the children of ClipChains later in the list.
|
||||
pub clip_chains_descriptors: Vec<ClipChainDescriptor>,
|
||||
|
||||
/// A HashMap of built ClipChains that are described by `clip_chains_descriptors`.
|
||||
pub clip_chains: FastHashMap<ClipChainId, ClipChain>,
|
||||
/// A vector of all ClipChains in this ClipScrollTree including those from
|
||||
/// ClipChainDescriptors and also those defined by the clipping node hierarchy.
|
||||
pub clip_chains: Vec<ClipChain>,
|
||||
|
||||
pub pending_scroll_offsets: FastHashMap<ScrollNodeIdType, (LayerPoint, ScrollClamping)>,
|
||||
pub pending_scroll_offsets: FastHashMap<ExternalScrollId, (LayerPoint, ScrollClamping)>,
|
||||
|
||||
/// The ClipId of the currently scrolling node. Used to allow the same
|
||||
/// node to scroll even if a touch operation leaves the boundaries of that node.
|
||||
|
@ -90,7 +92,9 @@ pub struct TransformUpdateState {
|
|||
pub parent_accumulated_scroll_offset: LayerVector2D,
|
||||
pub nearest_scrolling_ancestor_offset: LayerVector2D,
|
||||
pub nearest_scrolling_ancestor_viewport: LayerRect,
|
||||
pub parent_clip_chain: ClipChain,
|
||||
|
||||
/// The index of the current parent's clip chain.
|
||||
pub parent_clip_chain_index: ClipChainIndex,
|
||||
|
||||
/// An id for keeping track of the axis-aligned space of this node. This is used in
|
||||
/// order to to track what kinds of clip optimizations can be done for a particular
|
||||
|
@ -113,7 +117,7 @@ impl ClipScrollTree {
|
|||
ClipScrollTree {
|
||||
nodes: FastHashMap::default(),
|
||||
clip_chains_descriptors: Vec::new(),
|
||||
clip_chains: FastHashMap::default(),
|
||||
clip_chains: vec![ClipChain::empty(&DeviceIntRect::zero())],
|
||||
pending_scroll_offsets: FastHashMap::default(),
|
||||
currently_scrolling_node_id: None,
|
||||
root_reference_frame_id: ClipId::root_reference_frame(dummy_pipeline),
|
||||
|
@ -211,7 +215,7 @@ impl ClipScrollTree {
|
|||
}
|
||||
|
||||
self.pipelines_to_discard.clear();
|
||||
self.clip_chains.clear();
|
||||
self.clip_chains = vec![ClipChain::empty(&DeviceIntRect::zero())];
|
||||
self.clip_chains_descriptors.clear();
|
||||
scroll_states
|
||||
}
|
||||
|
@ -219,11 +223,11 @@ impl ClipScrollTree {
|
|||
pub fn scroll_node(
|
||||
&mut self,
|
||||
origin: LayerPoint,
|
||||
id: ScrollNodeIdType,
|
||||
id: ExternalScrollId,
|
||||
clamp: ScrollClamping
|
||||
) -> bool {
|
||||
for (clip_id, node) in &mut self.nodes {
|
||||
if node.matches_id(*clip_id, id) {
|
||||
for node in &mut self.nodes.values_mut() {
|
||||
if node.matches_external_id(id) {
|
||||
return node.set_scroll_origin(&origin, clamp);
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +325,8 @@ impl ClipScrollTree {
|
|||
return;
|
||||
}
|
||||
|
||||
self.clip_chains[0] = ClipChain::empty(screen_rect);
|
||||
|
||||
let root_reference_frame_id = self.root_reference_frame_id();
|
||||
let mut state = TransformUpdateState {
|
||||
parent_reference_frame_transform: LayerToWorldTransform::create_translation(
|
||||
|
@ -331,7 +337,7 @@ impl ClipScrollTree {
|
|||
parent_accumulated_scroll_offset: LayerVector2D::zero(),
|
||||
nearest_scrolling_ancestor_offset: LayerVector2D::zero(),
|
||||
nearest_scrolling_ancestor_viewport: LayerRect::zero(),
|
||||
parent_clip_chain: ClipChain::empty(screen_rect),
|
||||
parent_clip_chain_index: ClipChainIndex(0),
|
||||
current_coordinate_system_id: CoordinateSystemId::root(),
|
||||
coordinate_system_relative_transform: TransformOrOffset::zero(),
|
||||
invertible: true,
|
||||
|
@ -384,6 +390,7 @@ impl ClipScrollTree {
|
|||
resource_cache,
|
||||
gpu_cache,
|
||||
scene_properties,
|
||||
&mut self.clip_chains,
|
||||
);
|
||||
|
||||
node.push_gpu_node_data(gpu_node_data);
|
||||
|
@ -417,21 +424,28 @@ impl ClipScrollTree {
|
|||
// ClipScrollNode clipping nodes. Here we start the ClipChain with a clone of the
|
||||
// parent's node, if necessary.
|
||||
let mut chain = match descriptor.parent {
|
||||
Some(id) => self.clip_chains[&id].clone(),
|
||||
Some(index) => self.clip_chains[index.0].clone(),
|
||||
None => ClipChain::empty(screen_rect),
|
||||
};
|
||||
|
||||
// Now we walk through each ClipScrollNode in the vector of clip nodes and
|
||||
// extract their ClipChain nodes to construct the final list.
|
||||
for clip_id in &descriptor.clips {
|
||||
if let Some(ref node_chain) = self.nodes[&clip_id].clip_chain {
|
||||
if let Some(ref nodes) = node_chain.nodes {
|
||||
chain.add_node((**nodes).clone());
|
||||
let node_clip_chain_index = match self.nodes[&clip_id].node_type {
|
||||
NodeType::Clip { clip_chain_index, .. } => clip_chain_index,
|
||||
_ => {
|
||||
warn!("Tried to create a clip chain with non-clipping node.");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(ref nodes) = self.clip_chains[node_clip_chain_index.0].nodes {
|
||||
chain.add_node((**nodes).clone());
|
||||
}
|
||||
}
|
||||
|
||||
self.clip_chains.insert(descriptor.id, chain);
|
||||
chain.parent_index = descriptor.parent;
|
||||
self.clip_chains[descriptor.index.0] = chain;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,30 +456,37 @@ impl ClipScrollTree {
|
|||
}
|
||||
|
||||
pub fn finalize_and_apply_pending_scroll_offsets(&mut self, old_states: ScrollStates) {
|
||||
for (clip_id, node) in &mut self.nodes {
|
||||
for node in self.nodes.values_mut() {
|
||||
let external_id = match node.node_type {
|
||||
NodeType::ScrollFrame(info) => info.external_id,
|
||||
_ => None,
|
||||
NodeType::ScrollFrame(ScrollFrameInfo { external_id: Some(id), ..} ) => id,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if let Some(external_id) = external_id {
|
||||
if let Some(scrolling_state) = old_states.get(&external_id) {
|
||||
node.apply_old_scrolling_state(scrolling_state);
|
||||
}
|
||||
|
||||
|
||||
let id = external_id.into();
|
||||
if let Some((offset, clamping)) = self.pending_scroll_offsets.remove(&id) {
|
||||
node.set_scroll_origin(&offset, clamping);
|
||||
}
|
||||
if let Some(scrolling_state) = old_states.get(&external_id) {
|
||||
node.apply_old_scrolling_state(scrolling_state);
|
||||
}
|
||||
|
||||
if let Some((offset, clamping)) = self.pending_scroll_offsets.remove(&clip_id.into()) {
|
||||
|
||||
if let Some((offset, clamping)) = self.pending_scroll_offsets.remove(&external_id) {
|
||||
node.set_scroll_origin(&offset, clamping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clip_node(
|
||||
&mut self,
|
||||
id: ClipId,
|
||||
parent_id: ClipId,
|
||||
handle: ClipSourcesHandle,
|
||||
clip_rect: LayerRect,
|
||||
) -> ClipChainIndex {
|
||||
let clip_chain_index = self.allocate_clip_chain();
|
||||
let node_type = NodeType::Clip { handle, clip_chain_index };
|
||||
let node = ClipScrollNode::new(id.pipeline_id(), Some(parent_id), &clip_rect, node_type);
|
||||
self.add_node(node, id);
|
||||
clip_chain_index
|
||||
}
|
||||
|
||||
pub fn add_sticky_frame(
|
||||
&mut self,
|
||||
id: ClipId,
|
||||
|
@ -484,11 +505,12 @@ impl ClipScrollTree {
|
|||
|
||||
pub fn add_clip_chain_descriptor(
|
||||
&mut self,
|
||||
id: ClipChainId,
|
||||
parent: Option<ClipChainId>,
|
||||
parent: Option<ClipChainIndex>,
|
||||
clips: Vec<ClipId>
|
||||
) {
|
||||
self.clip_chains_descriptors.push(ClipChainDescriptor { id, parent, clips });
|
||||
) -> ClipChainIndex {
|
||||
let index = self.allocate_clip_chain();
|
||||
self.clip_chains_descriptors.push(ClipChainDescriptor { index, parent, clips });
|
||||
index
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, node: ClipScrollNode, id: ClipId) {
|
||||
|
@ -515,11 +537,11 @@ impl ClipScrollTree {
|
|||
let node = self.nodes.get(id).unwrap();
|
||||
|
||||
match node.node_type {
|
||||
NodeType::Clip(ref clip_sources_handle) => {
|
||||
NodeType::Clip { ref handle, .. } => {
|
||||
pt.new_level("Clip".to_owned());
|
||||
|
||||
pt.add_item(format!("id: {:?}", id));
|
||||
let clips = clip_store.get(&clip_sources_handle).clips();
|
||||
let clips = clip_store.get(&handle).clips();
|
||||
pt.new_level(format!("Clip Sources [{}]", clips.len()));
|
||||
for source in clips {
|
||||
pt.add_item(format!("{:?}", source));
|
||||
|
@ -581,11 +603,15 @@ impl ClipScrollTree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_clip_chain(&self, id: &ClipId) -> Option<&ClipChain> {
|
||||
match id {
|
||||
&ClipId::ClipChain(clip_chain_id) => Some(&self.clip_chains[&clip_chain_id]),
|
||||
_ => self.nodes[id].clip_chain.as_ref(),
|
||||
}
|
||||
pub fn allocate_clip_chain(&mut self) -> ClipChainIndex {
|
||||
debug_assert!(!self.clip_chains.is_empty());
|
||||
let new_clip_chain =self.clip_chains[0].clone();
|
||||
self.clip_chains.push(new_clip_chain);
|
||||
ClipChainIndex(self.clip_chains.len() - 1)
|
||||
}
|
||||
|
||||
pub fn get_clip_chain(&self, index: ClipChainIndex) -> &ClipChain {
|
||||
&self.clip_chains[index.0]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -438,6 +438,7 @@ pub struct Texture {
|
|||
render_target: Option<RenderTargetInfo>,
|
||||
fbo_ids: Vec<FBOId>,
|
||||
depth_rb: Option<RBOId>,
|
||||
last_frame_used: FrameId,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
|
@ -473,6 +474,10 @@ impl Texture {
|
|||
self.render_target.as_ref()
|
||||
}
|
||||
|
||||
pub fn used_in_frame(&self, frame_id: FrameId) -> bool {
|
||||
self.last_frame_used == frame_id
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
pub fn into_external(mut self) -> ExternalTexture {
|
||||
let ext = ExternalTexture {
|
||||
|
@ -940,6 +945,7 @@ impl Device {
|
|||
render_target: None,
|
||||
fbo_ids: vec![],
|
||||
depth_rb: None,
|
||||
last_frame_used: self.frame_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1019,6 +1025,7 @@ impl Device {
|
|||
texture.filter = filter;
|
||||
texture.layer_count = layer_count;
|
||||
texture.render_target = render_target;
|
||||
texture.last_frame_used = self.frame_id;
|
||||
|
||||
self.bind_texture(DEFAULT_TEXTURE, texture);
|
||||
self.set_texture_parameters(texture.target, filter);
|
||||
|
|
|
@ -3,21 +3,22 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BuiltDisplayListIter, ClipAndScrollInfo, ClipId, ColorF, ComplexClipRegion};
|
||||
use api::{DevicePixelScale, DeviceUintRect, DeviceUintSize, DisplayItemRef, DocumentLayer, Epoch};
|
||||
use api::{ExternalScrollId, FilterOp, IframeDisplayItem, ImageDisplayItem, ItemRange, LayerPoint};
|
||||
use api::{BuiltDisplayListIter, ClipId, ColorF, ComplexClipRegion, DevicePixelScale};
|
||||
use api::{DeviceUintRect, DeviceUintSize, DisplayItemRef, DocumentLayer, Epoch, ExternalScrollId};
|
||||
use api::{FilterOp, IframeDisplayItem, ImageDisplayItem, ItemRange, LayerPoint};
|
||||
use api::{LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D, LayoutSize, PipelineId};
|
||||
use api::{ScrollClamping, ScrollEventPhase, ScrollFrameDisplayItem, ScrollLocation};
|
||||
use api::{ScrollNodeIdType, ScrollNodeState, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem};
|
||||
use api::{StackingContext, TileOffset, TransformStyle, WorldPoint};
|
||||
use api::{ScrollNodeState, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem, StackingContext};
|
||||
use api::{TileOffset, TransformStyle, WorldPoint};
|
||||
use clip::ClipRegion;
|
||||
use clip_scroll_node::StickyFrameInfo;
|
||||
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollTree, ScrollStates};
|
||||
use euclid::rect;
|
||||
use frame_builder::{FrameBuilder, FrameBuilderConfig, ScrollbarInfo};
|
||||
use gpu_cache::GpuCache;
|
||||
use hit_test::HitTester;
|
||||
use internal_types::{FastHashMap, FastHashSet, RenderedDocument};
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters};
|
||||
use resource_cache::{FontInstanceMap,ResourceCache, TiledImageMap};
|
||||
use scene::{Scene, StackingContextHelpers, ScenePipeline, SceneProperties};
|
||||
|
@ -36,6 +37,53 @@ static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF {
|
|||
a: 0.6,
|
||||
};
|
||||
|
||||
/// A data structure that keeps track of mapping between API clip ids and the indices
|
||||
/// used internally in the ClipScrollTree to avoid having to do HashMap lookups. This
|
||||
/// also includes a small LRU cache. Currently the cache is small (1 entry), but in the
|
||||
/// future we could use uluru here to do something more involved.
|
||||
pub struct ClipIdToIndexMapper {
|
||||
map: FastHashMap<ClipId, ClipChainIndex>,
|
||||
cached_index: Option<(ClipId, ClipChainIndex)>,
|
||||
}
|
||||
|
||||
impl ClipIdToIndexMapper {
|
||||
fn new() -> ClipIdToIndexMapper {
|
||||
ClipIdToIndexMapper {
|
||||
map: FastHashMap::default(),
|
||||
cached_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, id: ClipId, index: ClipChainIndex) {
|
||||
debug_assert!(!self.map.contains_key(&id));
|
||||
self.map.insert(id, index);
|
||||
}
|
||||
|
||||
pub fn map_to_parent_clip_chain(&mut self, id: ClipId, parent_id: &ClipId) {
|
||||
let parent_chain_index = self.map_clip_id(parent_id);
|
||||
self.add(id, parent_chain_index);
|
||||
}
|
||||
|
||||
pub fn map_clip_id(&mut self, id: &ClipId) -> ClipChainIndex {
|
||||
match self.cached_index {
|
||||
Some((cached_id, cached_index)) if cached_id == *id => return cached_index,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.map[id]
|
||||
}
|
||||
|
||||
pub fn map_clip_id_and_cache_result(&mut self, id: &ClipId) -> ClipChainIndex {
|
||||
let index = self.map_clip_id(id);
|
||||
self.cached_index = Some((*id, index));
|
||||
index
|
||||
}
|
||||
|
||||
pub fn simple_scroll_and_clip_chain(&mut self, id: &ClipId) -> ScrollNodeAndClipChain {
|
||||
ScrollNodeAndClipChain::new(*id, self.map_clip_id(&id))
|
||||
}
|
||||
}
|
||||
|
||||
struct FlattenContext<'a> {
|
||||
scene: &'a Scene,
|
||||
builder: FrameBuilder,
|
||||
|
@ -45,6 +93,7 @@ struct FlattenContext<'a> {
|
|||
pipeline_epochs: Vec<(PipelineId, Epoch)>,
|
||||
replacements: Vec<(ClipId, ClipId)>,
|
||||
output_pipelines: &'a FastHashSet<PipelineId>,
|
||||
id_to_index_mapper: ClipIdToIndexMapper,
|
||||
}
|
||||
|
||||
impl<'a> FlattenContext<'a> {
|
||||
|
@ -104,13 +153,23 @@ impl<'a> FlattenContext<'a> {
|
|||
let root_reference_frame_id = ClipId::root_reference_frame(pipeline_id);
|
||||
let root_scroll_frame_id = ClipId::root_scroll_node(pipeline_id);
|
||||
|
||||
let root_clip_chain_index =
|
||||
self.id_to_index_mapper.map_clip_id_and_cache_result(&root_reference_frame_id);
|
||||
let root_reference_frame_clip_and_scroll = ScrollNodeAndClipChain::new(
|
||||
root_reference_frame_id,
|
||||
root_clip_chain_index,
|
||||
);
|
||||
|
||||
self.builder.push_stacking_context(
|
||||
pipeline_id,
|
||||
CompositeOps::default(),
|
||||
TransformStyle::Flat,
|
||||
true,
|
||||
true,
|
||||
ClipAndScrollInfo::simple(root_scroll_frame_id),
|
||||
ScrollNodeAndClipChain::new(
|
||||
ClipId::root_scroll_node(pipeline_id),
|
||||
root_clip_chain_index,
|
||||
),
|
||||
self.output_pipelines,
|
||||
);
|
||||
|
||||
|
@ -122,7 +181,7 @@ impl<'a> FlattenContext<'a> {
|
|||
let root_bounds = LayerRect::new(LayerPoint::zero(), *frame_size);
|
||||
let info = LayerPrimitiveInfo::new(root_bounds);
|
||||
self.builder.add_solid_rectangle(
|
||||
ClipAndScrollInfo::simple(root_reference_frame_id),
|
||||
root_reference_frame_clip_and_scroll,
|
||||
&info,
|
||||
bg_color,
|
||||
None,
|
||||
|
@ -142,7 +201,7 @@ impl<'a> FlattenContext<'a> {
|
|||
let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0));
|
||||
let container_rect = LayerRect::new(LayerPoint::zero(), *frame_size);
|
||||
self.builder.add_scroll_bar(
|
||||
ClipAndScrollInfo::simple(root_reference_frame_id),
|
||||
root_reference_frame_clip_and_scroll,
|
||||
&LayerPrimitiveInfo::new(scrollbar_rect),
|
||||
DEFAULT_SCROLLBAR_COLOR,
|
||||
ScrollbarInfo(root_scroll_frame_id, container_rect),
|
||||
|
@ -184,19 +243,13 @@ impl<'a> FlattenContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn flatten_clip(
|
||||
&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
parent_id: &ClipId,
|
||||
new_clip_id: &ClipId,
|
||||
clip_region: ClipRegion,
|
||||
) {
|
||||
fn flatten_clip(&mut self, parent_id: &ClipId, new_clip_id: &ClipId, clip_region: ClipRegion) {
|
||||
self.builder.add_clip_node(
|
||||
*new_clip_id,
|
||||
*parent_id,
|
||||
pipeline_id,
|
||||
clip_region,
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -205,7 +258,7 @@ impl<'a> FlattenContext<'a> {
|
|||
item: &DisplayItemRef,
|
||||
info: &ScrollFrameDisplayItem,
|
||||
pipeline_id: PipelineId,
|
||||
clip_and_scroll: &ClipAndScrollInfo,
|
||||
clip_and_scroll: &ScrollNodeAndClipChain,
|
||||
reference_frame_relative_offset: &LayerVector2D,
|
||||
) {
|
||||
let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0);
|
||||
|
@ -229,9 +282,9 @@ impl<'a> FlattenContext<'a> {
|
|||
self.builder.add_clip_node(
|
||||
info.clip_id,
|
||||
clip_and_scroll.scroll_node_id,
|
||||
pipeline_id,
|
||||
clip_region,
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
|
||||
self.builder.add_scroll_frame(
|
||||
|
@ -243,6 +296,7 @@ impl<'a> FlattenContext<'a> {
|
|||
&content_rect.size,
|
||||
info.scroll_sensitivity,
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -250,7 +304,8 @@ impl<'a> FlattenContext<'a> {
|
|||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
context_scroll_node_id: ClipId,
|
||||
unreplaced_scroll_id: ClipId,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
mut reference_frame_relative_offset: LayerVector2D,
|
||||
bounds: &LayerRect,
|
||||
stacking_context: &StackingContext,
|
||||
|
@ -279,7 +334,7 @@ impl<'a> FlattenContext<'a> {
|
|||
|
||||
if stacking_context.scroll_policy == ScrollPolicy::Fixed {
|
||||
self.replacements.push((
|
||||
context_scroll_node_id,
|
||||
unreplaced_scroll_id,
|
||||
self.builder.current_reference_frame_id(),
|
||||
));
|
||||
}
|
||||
|
@ -296,30 +351,33 @@ impl<'a> FlattenContext<'a> {
|
|||
);
|
||||
|
||||
let reference_frame_bounds = LayerRect::new(LayerPoint::zero(), bounds.size);
|
||||
let mut parent_id = self.apply_scroll_frame_id_replacement(context_scroll_node_id);
|
||||
self.builder.push_reference_frame(
|
||||
reference_frame_id,
|
||||
Some(parent_id),
|
||||
Some(clip_and_scroll.scroll_node_id),
|
||||
pipeline_id,
|
||||
&reference_frame_bounds,
|
||||
stacking_context.transform,
|
||||
stacking_context.perspective,
|
||||
reference_frame_relative_offset,
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
self.replacements.push((context_scroll_node_id, reference_frame_id));
|
||||
self.replacements.push((unreplaced_scroll_id, reference_frame_id));
|
||||
reference_frame_relative_offset = LayerVector2D::zero();
|
||||
}
|
||||
|
||||
let sc_scroll_node_id = self.apply_scroll_frame_id_replacement(context_scroll_node_id);
|
||||
|
||||
// We apply the replacements one more time in case we need to set it to a replacement
|
||||
// that we just pushed above.
|
||||
let new_scroll_node = self.apply_scroll_frame_id_replacement(unreplaced_scroll_id);
|
||||
let stacking_context_clip_and_scroll =
|
||||
self.id_to_index_mapper.simple_scroll_and_clip_chain(&new_scroll_node);
|
||||
self.builder.push_stacking_context(
|
||||
pipeline_id,
|
||||
composition_operations,
|
||||
stacking_context.transform_style,
|
||||
is_backface_visible,
|
||||
false,
|
||||
ClipAndScrollInfo::simple(sc_scroll_node_id),
|
||||
stacking_context_clip_and_scroll,
|
||||
self.output_pipelines,
|
||||
);
|
||||
|
||||
|
@ -345,8 +403,7 @@ impl<'a> FlattenContext<'a> {
|
|||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &IframeDisplayItem,
|
||||
parent_pipeline_id: PipelineId,
|
||||
clip_and_scroll: &ClipAndScrollInfo,
|
||||
clip_and_scroll: &ScrollNodeAndClipChain,
|
||||
reference_frame_relative_offset: &LayerVector2D,
|
||||
) {
|
||||
let iframe_pipeline_id = info.pipeline_id;
|
||||
|
@ -358,12 +415,12 @@ impl<'a> FlattenContext<'a> {
|
|||
self.builder.add_clip_node(
|
||||
info.clip_id,
|
||||
clip_and_scroll.scroll_node_id,
|
||||
parent_pipeline_id,
|
||||
ClipRegion::create_for_clip_node_with_local_clip(
|
||||
&item.local_clip(),
|
||||
&reference_frame_relative_offset
|
||||
),
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
|
||||
self.pipeline_epochs.push((iframe_pipeline_id, pipeline.epoch));
|
||||
|
@ -380,6 +437,7 @@ impl<'a> FlattenContext<'a> {
|
|||
None,
|
||||
origin,
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
|
||||
self.builder.add_scroll_frame(
|
||||
|
@ -391,6 +449,7 @@ impl<'a> FlattenContext<'a> {
|
|||
&pipeline.content_size,
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
self.clip_scroll_tree,
|
||||
&mut self.id_to_index_mapper,
|
||||
);
|
||||
|
||||
self.flatten_root(&mut pipeline.display_list.iter(), iframe_pipeline_id, &iframe_rect.size);
|
||||
|
@ -404,7 +463,11 @@ impl<'a> FlattenContext<'a> {
|
|||
pipeline_id: PipelineId,
|
||||
reference_frame_relative_offset: LayerVector2D,
|
||||
) -> Option<BuiltDisplayListIter<'a>> {
|
||||
let mut clip_and_scroll = item.clip_and_scroll();
|
||||
let clip_and_scroll = item.clip_and_scroll();
|
||||
let mut clip_and_scroll = ScrollNodeAndClipChain::new(
|
||||
clip_and_scroll.scroll_node_id,
|
||||
self.id_to_index_mapper.map_clip_id_and_cache_result(&clip_and_scroll.clip_node_id()),
|
||||
);
|
||||
|
||||
let unreplaced_scroll_id = clip_and_scroll.scroll_node_id;
|
||||
clip_and_scroll.scroll_node_id =
|
||||
|
@ -557,6 +620,7 @@ impl<'a> FlattenContext<'a> {
|
|||
&mut subtraversal,
|
||||
pipeline_id,
|
||||
unreplaced_scroll_id,
|
||||
clip_and_scroll,
|
||||
reference_frame_relative_offset,
|
||||
&item.rect(),
|
||||
&info.stacking_context,
|
||||
|
@ -569,7 +633,6 @@ impl<'a> FlattenContext<'a> {
|
|||
self.flatten_iframe(
|
||||
&item,
|
||||
info,
|
||||
pipeline_id,
|
||||
&clip_and_scroll,
|
||||
&reference_frame_relative_offset
|
||||
);
|
||||
|
@ -582,16 +645,16 @@ impl<'a> FlattenContext<'a> {
|
|||
info.image_mask,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
self.flatten_clip(
|
||||
pipeline_id,
|
||||
&clip_and_scroll.scroll_node_id,
|
||||
&info.id,
|
||||
clip_region,
|
||||
);
|
||||
self.flatten_clip(&clip_and_scroll.scroll_node_id, &info.id, clip_region);
|
||||
}
|
||||
SpecificDisplayItem::ClipChain(ref info) => {
|
||||
let items = self.get_clip_chain_items(pipeline_id, item.clip_chain_items());
|
||||
self.clip_scroll_tree.add_clip_chain_descriptor(info.id, info.parent, items);
|
||||
let parent = info.parent.map(|id|
|
||||
self.id_to_index_mapper.map_clip_id(&ClipId::ClipChain(id))
|
||||
);
|
||||
let clip_chain_index =
|
||||
self.clip_scroll_tree.add_clip_chain_descriptor(parent, items);
|
||||
self.id_to_index_mapper.add(ClipId::ClipChain(info.id), clip_chain_index);
|
||||
},
|
||||
SpecificDisplayItem::ScrollFrame(ref info) => {
|
||||
self.flatten_scroll_frame(
|
||||
|
@ -610,12 +673,14 @@ impl<'a> FlattenContext<'a> {
|
|||
info.horizontal_offset_bounds,
|
||||
info.previously_applied_offset,
|
||||
);
|
||||
let parent_id = clip_and_scroll.scroll_node_id;
|
||||
self.clip_scroll_tree.add_sticky_frame(
|
||||
info.id,
|
||||
clip_and_scroll.scroll_node_id, /* parent id */
|
||||
parent_id,
|
||||
frame_rect,
|
||||
sticky_frame_info
|
||||
);
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(info.id, &parent_id);
|
||||
}
|
||||
|
||||
// Do nothing; these are dummy items for the display list parser
|
||||
|
@ -650,7 +715,7 @@ impl<'a> FlattenContext<'a> {
|
|||
/// takes care of the decomposition required by the internal tiling of the image.
|
||||
fn decompose_image(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
prim_info: &LayerPrimitiveInfo,
|
||||
info: &ImageDisplayItem,
|
||||
image_size: DeviceUintSize,
|
||||
|
@ -696,7 +761,7 @@ impl<'a> FlattenContext<'a> {
|
|||
|
||||
fn decompose_image_row(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
prim_info: &LayerPrimitiveInfo,
|
||||
info: &ImageDisplayItem,
|
||||
image_size: DeviceUintSize,
|
||||
|
@ -742,7 +807,7 @@ impl<'a> FlattenContext<'a> {
|
|||
|
||||
fn decompose_tiled_image(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
prim_info: &LayerPrimitiveInfo,
|
||||
info: &ImageDisplayItem,
|
||||
image_size: DeviceUintSize,
|
||||
|
@ -878,7 +943,7 @@ impl<'a> FlattenContext<'a> {
|
|||
|
||||
fn add_tile_primitive(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
prim_info: &LayerPrimitiveInfo,
|
||||
info: &ImageDisplayItem,
|
||||
tile_offset: TileOffset,
|
||||
|
@ -983,7 +1048,7 @@ impl FrameContext {
|
|||
pub fn scroll_node(
|
||||
&mut self,
|
||||
origin: LayerPoint,
|
||||
id: ScrollNodeIdType,
|
||||
id: ExternalScrollId,
|
||||
clamp: ScrollClamping
|
||||
) -> bool {
|
||||
self.clip_scroll_tree.scroll_node(origin, id, clamp)
|
||||
|
@ -1056,6 +1121,7 @@ impl FrameContext {
|
|||
pipeline_epochs: Vec::new(),
|
||||
replacements: Vec::new(),
|
||||
output_pipelines,
|
||||
id_to_index_mapper: ClipIdToIndexMapper::new(),
|
||||
};
|
||||
|
||||
roller.builder.push_root(
|
||||
|
@ -1063,6 +1129,7 @@ impl FrameContext {
|
|||
&root_pipeline.viewport_size,
|
||||
&root_pipeline.content_size,
|
||||
roller.clip_scroll_tree,
|
||||
&mut roller.id_to_index_mapper,
|
||||
);
|
||||
|
||||
roller.builder.setup_viewport_offset(
|
||||
|
|
|
@ -2,35 +2,34 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, ClipAndScrollInfo};
|
||||
use api::{ClipId, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
|
||||
use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode};
|
||||
use api::{ExternalScrollId, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey};
|
||||
use api::{ImageRendering, ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize};
|
||||
use api::{LayerTransform, LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation};
|
||||
use api::{LineStyle, LocalClip, PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode};
|
||||
use api::{ScrollSensitivity, Shadow, TexelRect, TileOffset, TransformStyle, WorldPoint};
|
||||
use api::{WorldToLayerTransform, YuvColorSpace, YuvData};
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, ClipId, ColorF};
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint};
|
||||
use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId};
|
||||
use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering};
|
||||
use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerTransform};
|
||||
use api::{LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip};
|
||||
use api::{PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow};
|
||||
use api::{TexelRect, TileOffset, TransformStyle, WorldPoint, WorldToLayerTransform, YuvColorSpace};
|
||||
use api::YuvData;
|
||||
use app_units::Au;
|
||||
use border::ImageBorderSegment;
|
||||
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore};
|
||||
use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore};
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType};
|
||||
use clip_scroll_tree::ClipScrollTree;
|
||||
use clip_scroll_tree::{ClipScrollTree, ClipChainIndex};
|
||||
use euclid::{SideOffsets2D, vec2};
|
||||
use frame::FrameId;
|
||||
use frame::{FrameId, ClipIdToIndexMapper};
|
||||
use glyph_rasterizer::FontInstance;
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle};
|
||||
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
|
||||
use hit_test::{HitTester, HitTestingItem, HitTestingRun};
|
||||
use internal_types::{FastHashMap, FastHashSet, RenderPassIndex};
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
||||
use prim_store::{BrushKind, BrushPrimitive, ImageCacheKey, YuvImagePrimitiveCpu};
|
||||
use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu, ImageSource, PrimitiveKind};
|
||||
use prim_store::{PrimitiveContainer, PrimitiveIndex};
|
||||
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu};
|
||||
use prim_store::{BrushSegmentDescriptor, PrimitiveRun, TextRunPrimitiveCpu};
|
||||
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, GradientPrimitiveCpu};
|
||||
use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer};
|
||||
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore};
|
||||
use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
|
||||
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
|
||||
use render_task::{ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
|
||||
use resource_cache::{ImageRequest, ResourceCache};
|
||||
use scene::{ScenePipeline, SceneProperties};
|
||||
use std::{mem, usize, f32};
|
||||
|
@ -90,10 +89,10 @@ pub struct FrameBuilder {
|
|||
|
||||
// A stack of the current shadow primitives.
|
||||
// The sub-Vec stores a buffer of fast-path primitives to be appended on pop.
|
||||
shadow_prim_stack: Vec<(PrimitiveIndex, Vec<(PrimitiveIndex, ClipAndScrollInfo)>)>,
|
||||
shadow_prim_stack: Vec<(PrimitiveIndex, Vec<(PrimitiveIndex, ScrollNodeAndClipChain)>)>,
|
||||
// If we're doing any fast-path shadows, we buffer the "real"
|
||||
// content here, to be appended when the shadow stack is empty.
|
||||
pending_shadow_contents: Vec<(PrimitiveIndex, ClipAndScrollInfo, LayerPrimitiveInfo)>,
|
||||
pending_shadow_contents: Vec<(PrimitiveIndex, ScrollNodeAndClipChain, LayerPrimitiveInfo)>,
|
||||
|
||||
scrollbar_prims: Vec<ScrollbarPrimitive>,
|
||||
|
||||
|
@ -150,14 +149,14 @@ impl PictureState {
|
|||
}
|
||||
|
||||
pub struct PrimitiveRunContext<'a> {
|
||||
pub clip_chain: Option<&'a ClipChain>,
|
||||
pub clip_chain: &'a ClipChain,
|
||||
pub scroll_node: &'a ClipScrollNode,
|
||||
pub clip_chain_rect_index: ClipChainRectIndex,
|
||||
}
|
||||
|
||||
impl<'a> PrimitiveRunContext<'a> {
|
||||
pub fn new(
|
||||
clip_chain: Option<&'a ClipChain>,
|
||||
clip_chain: &'a ClipChain,
|
||||
scroll_node: &'a ClipScrollNode,
|
||||
clip_chain_rect_index: ClipChainRectIndex,
|
||||
) -> Self {
|
||||
|
@ -252,7 +251,7 @@ impl FrameBuilder {
|
|||
pub fn add_primitive_to_hit_testing_list(
|
||||
&mut self,
|
||||
info: &LayerPrimitiveInfo,
|
||||
clip_and_scroll: ClipAndScrollInfo
|
||||
clip_and_scroll: ScrollNodeAndClipChain
|
||||
) {
|
||||
let tag = match info.tag {
|
||||
Some(tag) => tag,
|
||||
|
@ -276,7 +275,7 @@ impl FrameBuilder {
|
|||
pub fn add_primitive_to_draw_list(
|
||||
&mut self,
|
||||
prim_index: PrimitiveIndex,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
) {
|
||||
// Add primitive to the top-most Picture on the stack.
|
||||
// TODO(gw): Let's consider removing the extra indirection
|
||||
|
@ -294,7 +293,7 @@ impl FrameBuilder {
|
|||
/// to the draw list.
|
||||
pub fn add_primitive(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
clip_sources: Vec<ClipSource>,
|
||||
container: PrimitiveContainer,
|
||||
|
@ -313,7 +312,7 @@ impl FrameBuilder {
|
|||
transform_style: TransformStyle,
|
||||
is_backface_visible: bool,
|
||||
is_pipeline_root: bool,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
output_pipelines: &FastHashSet<PipelineId>,
|
||||
) {
|
||||
// Construct the necessary set of Picture primitives
|
||||
|
@ -640,6 +639,7 @@ impl FrameBuilder {
|
|||
source_perspective: Option<LayoutTransform>,
|
||||
origin_in_parent_reference_frame: LayerVector2D,
|
||||
clip_scroll_tree: &mut ClipScrollTree,
|
||||
id_to_index_mapper: &mut ClipIdToIndexMapper,
|
||||
) {
|
||||
let node = ClipScrollNode::new_reference_frame(
|
||||
parent_id,
|
||||
|
@ -651,6 +651,12 @@ impl FrameBuilder {
|
|||
);
|
||||
clip_scroll_tree.add_node(node, reference_frame_id);
|
||||
self.reference_frame_stack.push(reference_frame_id);
|
||||
|
||||
match parent_id {
|
||||
Some(ref parent_id) =>
|
||||
id_to_index_mapper.map_to_parent_clip_chain(reference_frame_id, parent_id),
|
||||
_ => id_to_index_mapper.add(reference_frame_id, ClipChainIndex(0)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_reference_frame_id(&self) -> ClipId {
|
||||
|
@ -682,6 +688,7 @@ impl FrameBuilder {
|
|||
viewport_size: &LayerSize,
|
||||
content_size: &LayerSize,
|
||||
clip_scroll_tree: &mut ClipScrollTree,
|
||||
id_to_index_mapper: &mut ClipIdToIndexMapper,
|
||||
) -> ClipId {
|
||||
let viewport_rect = LayerRect::new(LayerPoint::zero(), *viewport_size);
|
||||
self.push_reference_frame(
|
||||
|
@ -693,6 +700,7 @@ impl FrameBuilder {
|
|||
None,
|
||||
LayerVector2D::zero(),
|
||||
clip_scroll_tree,
|
||||
id_to_index_mapper,
|
||||
);
|
||||
|
||||
let topmost_scrolling_node_id = ClipId::root_scroll_node(pipeline_id);
|
||||
|
@ -707,6 +715,7 @@ impl FrameBuilder {
|
|||
content_size,
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
clip_scroll_tree,
|
||||
id_to_index_mapper,
|
||||
);
|
||||
|
||||
topmost_scrolling_node_id
|
||||
|
@ -716,18 +725,23 @@ impl FrameBuilder {
|
|||
&mut self,
|
||||
new_node_id: ClipId,
|
||||
parent_id: ClipId,
|
||||
pipeline_id: PipelineId,
|
||||
clip_region: ClipRegion,
|
||||
clip_scroll_tree: &mut ClipScrollTree,
|
||||
id_to_index_mapper: &mut ClipIdToIndexMapper,
|
||||
) {
|
||||
let clip_rect = clip_region.main;
|
||||
let clip_sources = ClipSources::from(clip_region);
|
||||
debug_assert!(clip_sources.has_clips());
|
||||
|
||||
debug_assert!(clip_sources.has_clips());
|
||||
let handle = self.clip_store.insert(clip_sources);
|
||||
|
||||
let node = ClipScrollNode::new_clip_node(pipeline_id, parent_id, handle, clip_rect);
|
||||
clip_scroll_tree.add_node(node, new_node_id);
|
||||
let clip_chain_index = clip_scroll_tree.add_clip_node(
|
||||
new_node_id,
|
||||
parent_id,
|
||||
handle,
|
||||
clip_rect
|
||||
);
|
||||
id_to_index_mapper.add(new_node_id, clip_chain_index);
|
||||
}
|
||||
|
||||
pub fn add_scroll_frame(
|
||||
|
@ -740,6 +754,7 @@ impl FrameBuilder {
|
|||
content_size: &LayerSize,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
clip_scroll_tree: &mut ClipScrollTree,
|
||||
id_to_index_mapper: &mut ClipIdToIndexMapper,
|
||||
) {
|
||||
let node = ClipScrollNode::new_scroll_frame(
|
||||
pipeline_id,
|
||||
|
@ -751,6 +766,7 @@ impl FrameBuilder {
|
|||
);
|
||||
|
||||
clip_scroll_tree.add_node(node, new_node_id);
|
||||
id_to_index_mapper.map_to_parent_clip_chain(new_node_id, &parent_id);
|
||||
}
|
||||
|
||||
pub fn pop_reference_frame(&mut self) {
|
||||
|
@ -760,7 +776,7 @@ impl FrameBuilder {
|
|||
pub fn push_shadow(
|
||||
&mut self,
|
||||
shadow: Shadow,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
) {
|
||||
let pipeline_id = self.sc_stack.last().unwrap().pipeline_id;
|
||||
|
@ -804,7 +820,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_solid_rectangle(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
color: ColorF,
|
||||
segments: Option<BrushSegmentDescriptor>,
|
||||
|
@ -833,7 +849,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_clear_rectangle(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
) {
|
||||
let prim = BrushPrimitive::new(
|
||||
|
@ -851,7 +867,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_scroll_bar(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
color: ColorF,
|
||||
scrollbar_info: ScrollbarInfo,
|
||||
|
@ -883,7 +899,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_line(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
wavy_line_thickness: f32,
|
||||
orientation: LineOrientation,
|
||||
|
@ -970,7 +986,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_border(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
border_item: &BorderDisplayItem,
|
||||
gradient_stops: ItemRange<GradientStop>,
|
||||
|
@ -1222,7 +1238,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_gradient(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
start_point: LayerPoint,
|
||||
end_point: LayerPoint,
|
||||
|
@ -1290,9 +1306,43 @@ impl FrameBuilder {
|
|||
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
|
||||
}
|
||||
|
||||
fn add_radial_gradient_impl(
|
||||
&mut self,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
start_center: LayerPoint,
|
||||
start_radius: f32,
|
||||
end_center: LayerPoint,
|
||||
end_radius: f32,
|
||||
ratio_xy: f32,
|
||||
stops: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
) {
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::RadialGradient {
|
||||
stops_range: stops,
|
||||
extend_mode,
|
||||
stops_handle: GpuCacheHandle::new(),
|
||||
start_center,
|
||||
end_center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(prim),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn add_radial_gradient(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
start_center: LayerPoint,
|
||||
start_radius: f32,
|
||||
|
@ -1304,40 +1354,44 @@ impl FrameBuilder {
|
|||
tile_size: LayerSize,
|
||||
tile_spacing: LayerSize,
|
||||
) {
|
||||
let tile_repeat = tile_size + tile_spacing;
|
||||
let prim_infos = info.decompose(
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
|
||||
let radial_gradient_cpu = RadialGradientPrimitiveCpu {
|
||||
stops_range: stops,
|
||||
extend_mode,
|
||||
gpu_data_count: 0,
|
||||
gpu_blocks: [
|
||||
[start_center.x, start_center.y, end_center.x, end_center.y].into(),
|
||||
[
|
||||
if prim_infos.is_empty() {
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
start_center,
|
||||
start_radius,
|
||||
end_center,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
);
|
||||
} else {
|
||||
for prim_info in prim_infos {
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
start_center,
|
||||
start_radius,
|
||||
end_center,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
pack_as_float(extend_mode as u32),
|
||||
].into(),
|
||||
[
|
||||
tile_size.width,
|
||||
tile_size.height,
|
||||
tile_repeat.width,
|
||||
tile_repeat.height,
|
||||
].into(),
|
||||
],
|
||||
};
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::RadialGradient(radial_gradient_cpu),
|
||||
);
|
||||
stops,
|
||||
extend_mode,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_text(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
run_offset: LayoutVector2D,
|
||||
info: &LayerPrimitiveInfo,
|
||||
font: &FontInstance,
|
||||
|
@ -1493,7 +1547,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_image(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
stretch_size: LayerSize,
|
||||
mut tile_spacing: LayerSize,
|
||||
|
@ -1573,7 +1627,7 @@ impl FrameBuilder {
|
|||
|
||||
pub fn add_yuv_image(
|
||||
&mut self,
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayerPrimitiveInfo,
|
||||
yuv_data: YuvData,
|
||||
color_space: YuvColorSpace,
|
||||
|
@ -1586,19 +1640,21 @@ impl FrameBuilder {
|
|||
YuvData::InterleavedYCbCr(plane_0) => [plane_0, ImageKey::DUMMY, ImageKey::DUMMY],
|
||||
};
|
||||
|
||||
let prim_cpu = YuvImagePrimitiveCpu {
|
||||
yuv_key,
|
||||
format,
|
||||
color_space,
|
||||
image_rendering,
|
||||
gpu_block: [info.rect.size.width, info.rect.size.height, 0.0, 0.0].into(),
|
||||
};
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::YuvImage {
|
||||
yuv_key,
|
||||
format,
|
||||
color_space,
|
||||
image_rendering,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::YuvImage(prim_cpu),
|
||||
PrimitiveContainer::Brush(prim),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1807,7 +1863,7 @@ impl FrameBuilder {
|
|||
let use_dual_source_blending = self.config.dual_source_blending_is_enabled &&
|
||||
self.config.dual_source_blending_is_supported;
|
||||
|
||||
for (pass_index, pass) in passes.iter_mut().enumerate() {
|
||||
for pass in &mut passes {
|
||||
let ctx = RenderTargetContext {
|
||||
device_pixel_scale,
|
||||
prim_store: &self.prim_store,
|
||||
|
@ -1823,7 +1879,6 @@ impl FrameBuilder {
|
|||
&mut render_tasks,
|
||||
&mut deferred_resolves,
|
||||
&self.clip_store,
|
||||
RenderPassIndex(pass_index),
|
||||
);
|
||||
|
||||
if let RenderPassKind::OffScreen { ref texture_cache, .. } = pass.kind {
|
||||
|
@ -1863,3 +1918,67 @@ impl FrameBuilder {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
trait PrimitiveInfoTiler {
|
||||
fn decompose(
|
||||
&self,
|
||||
tile_size: LayerSize,
|
||||
tile_spacing: LayerSize,
|
||||
max_prims: usize,
|
||||
) -> Vec<LayerPrimitiveInfo>;
|
||||
}
|
||||
|
||||
impl PrimitiveInfoTiler for LayerPrimitiveInfo {
|
||||
fn decompose(
|
||||
&self,
|
||||
tile_size: LayerSize,
|
||||
tile_spacing: LayerSize,
|
||||
max_prims: usize,
|
||||
) -> Vec<LayerPrimitiveInfo> {
|
||||
let mut prims = Vec::new();
|
||||
let tile_repeat = tile_size + tile_spacing;
|
||||
|
||||
if tile_repeat.width <= 0.0 ||
|
||||
tile_repeat.height <= 0.0 {
|
||||
return prims;
|
||||
}
|
||||
|
||||
if tile_repeat.width < self.rect.size.width ||
|
||||
tile_repeat.height < self.rect.size.height {
|
||||
let local_clip = self.local_clip.clip_by(&self.rect);
|
||||
let rect_p0 = self.rect.origin;
|
||||
let rect_p1 = self.rect.bottom_right();
|
||||
|
||||
let mut y0 = rect_p0.y;
|
||||
while y0 < rect_p1.y {
|
||||
let mut x0 = rect_p0.x;
|
||||
|
||||
while x0 < rect_p1.x {
|
||||
prims.push(LayerPrimitiveInfo {
|
||||
rect: LayerRect::new(
|
||||
LayerPoint::new(x0, y0),
|
||||
tile_size,
|
||||
),
|
||||
local_clip,
|
||||
is_backface_visible: self.is_backface_visible,
|
||||
tag: self.tag,
|
||||
});
|
||||
|
||||
// Mostly a safety against a crazy number of primitives
|
||||
// being generated. If we exceed that amount, just bail
|
||||
// out and only draw the maximum amount.
|
||||
if prims.len() > max_prims {
|
||||
warn!("too many prims found due to repeat/tile. dropping extra prims!");
|
||||
return prims;
|
||||
}
|
||||
|
||||
x0 += tile_repeat.width;
|
||||
}
|
||||
|
||||
y0 += tile_repeat.height;
|
||||
}
|
||||
}
|
||||
|
||||
prims
|
||||
}
|
||||
}
|
||||
|
|
|
@ -628,16 +628,17 @@ fn rasterize_200_glyphs() {
|
|||
// This test loads a font from disc, the renders 4 requests containing
|
||||
// 50 glyphs each, deletes the font and waits for the result.
|
||||
|
||||
use rayon::Configuration;
|
||||
use rayon::ThreadPoolBuilder;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
let worker_config = Configuration::new()
|
||||
let worker = ThreadPoolBuilder::new()
|
||||
.thread_name(|idx|{ format!("WRWorker#{}", idx) })
|
||||
.start_handler(move |idx| {
|
||||
register_thread_with_profiler(format!("WRWorker#{}", idx));
|
||||
});
|
||||
let workers = Arc::new(ThreadPool::new(worker_config).unwrap());
|
||||
})
|
||||
.build();
|
||||
let workers = Arc::new(worker.unwrap());
|
||||
let mut glyph_rasterizer = GlyphRasterizer::new(workers).unwrap();
|
||||
let mut glyph_cache = GlyphCache::new();
|
||||
let mut gpu_cache = GpuCache::new();
|
||||
|
|
|
@ -147,6 +147,14 @@ impl From<CompositePrimitiveInstance> for PrimitiveInstance {
|
|||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags that define how the common brush shader
|
||||
/// code should process this instance.
|
||||
pub struct BrushFlags: u8 {
|
||||
const PERSPECTIVE_INTERPOLATION = 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gw): While we are comverting things over, we
|
||||
// need to have the instance be the same
|
||||
// size as an old PrimitiveInstance. In the
|
||||
|
@ -164,6 +172,7 @@ pub struct BrushInstance {
|
|||
pub z: i32,
|
||||
pub segment_index: i32,
|
||||
pub edge_flags: EdgeAaSegmentMask,
|
||||
pub brush_flags: BrushFlags,
|
||||
pub user_data: [i32; 3],
|
||||
}
|
||||
|
||||
|
@ -175,7 +184,9 @@ impl From<BrushInstance> for PrimitiveInstance {
|
|||
instance.prim_address.as_int(),
|
||||
((instance.clip_chain_rect_index.0 as i32) << 16) | instance.scroll_id.0 as i32,
|
||||
instance.z,
|
||||
instance.segment_index | ((instance.edge_flags.bits() as i32) << 16),
|
||||
instance.segment_index |
|
||||
((instance.edge_flags.bits() as i32) << 16) |
|
||||
((instance.brush_flags.bits() as i32) << 24),
|
||||
instance.user_data[0],
|
||||
instance.user_data[1],
|
||||
instance.user_data[2],
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, ClipAndScrollInfo, ClipId, ClipMode, HitTestFlags, HitTestItem};
|
||||
use api::{HitTestResult, ItemTag, LayerPoint, LayerPrimitiveInfo, LayerRect};
|
||||
use api::{LayerToWorldTransform, LocalClip, PipelineId, WorldPoint};
|
||||
use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag};
|
||||
use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LayerToWorldTransform, LocalClip, PipelineId};
|
||||
use api::WorldPoint;
|
||||
use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point};
|
||||
use clip_scroll_node::{ClipScrollNode, NodeType};
|
||||
use clip_scroll_tree::ClipScrollTree;
|
||||
use clip_scroll_tree::{ClipChainIndex, ClipScrollTree};
|
||||
use internal_types::FastHashMap;
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
|
||||
/// 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,
|
||||
|
@ -33,11 +34,21 @@ pub struct HitTestClipScrollNode {
|
|||
/// handled the same way during hit testing. Once we represent all ClipChains
|
||||
/// using ClipChainDescriptors, we can get rid of this and just use the
|
||||
/// ClipChainDescriptor here.
|
||||
#[derive(Clone)]
|
||||
struct HitTestClipChainDescriptor {
|
||||
parent: Option<ClipId>,
|
||||
parent: Option<ClipChainIndex>,
|
||||
clips: Vec<ClipId>,
|
||||
}
|
||||
|
||||
impl HitTestClipChainDescriptor {
|
||||
fn empty() -> HitTestClipChainDescriptor {
|
||||
HitTestClipChainDescriptor {
|
||||
parent: None,
|
||||
clips: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HitTestingItem {
|
||||
rect: LayerRect,
|
||||
|
@ -56,7 +67,7 @@ impl HitTestingItem {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HitTestingRun(pub Vec<HitTestingItem>, pub ClipAndScrollInfo);
|
||||
pub struct HitTestingRun(pub Vec<HitTestingItem>, pub ScrollNodeAndClipChain);
|
||||
|
||||
enum HitTestRegion {
|
||||
Rectangle(LayerRect),
|
||||
|
@ -78,7 +89,7 @@ impl HitTestRegion {
|
|||
pub struct HitTester {
|
||||
runs: Vec<HitTestingRun>,
|
||||
nodes: FastHashMap<ClipId, HitTestClipScrollNode>,
|
||||
clip_chains: FastHashMap<ClipId, HitTestClipChainDescriptor>,
|
||||
clip_chains: Vec<HitTestClipChainDescriptor>,
|
||||
}
|
||||
|
||||
impl HitTester {
|
||||
|
@ -90,7 +101,7 @@ impl HitTester {
|
|||
let mut hit_tester = HitTester {
|
||||
runs: runs.clone(),
|
||||
nodes: FastHashMap::default(),
|
||||
clip_chains: FastHashMap::default(),
|
||||
clip_chains: Vec::new(),
|
||||
};
|
||||
hit_tester.read_clip_scroll_tree(clip_scroll_tree, clip_store);
|
||||
hit_tester
|
||||
|
@ -102,6 +113,11 @@ impl HitTester {
|
|||
clip_store: &ClipStore
|
||||
) {
|
||||
self.nodes.clear();
|
||||
self.clip_chains.clear();
|
||||
self.clip_chains.resize(
|
||||
clip_scroll_tree.clip_chains.len(),
|
||||
HitTestClipChainDescriptor::empty()
|
||||
);
|
||||
|
||||
for (id, node) in &clip_scroll_tree.nodes {
|
||||
self.nodes.insert(*id, HitTestClipScrollNode {
|
||||
|
@ -111,52 +127,50 @@ impl HitTester {
|
|||
node_origin: node.local_viewport_rect.origin,
|
||||
});
|
||||
|
||||
self.clip_chains.insert(*id, HitTestClipChainDescriptor {
|
||||
parent: node.parent,
|
||||
clips: vec![*id],
|
||||
});
|
||||
if let NodeType::Clip { clip_chain_index, .. } = node.node_type {
|
||||
let clip_chain = self.clip_chains.get_mut(clip_chain_index.0).unwrap();
|
||||
clip_chain.parent =
|
||||
clip_scroll_tree.get_clip_chain(clip_chain_index).parent_index;
|
||||
clip_chain.clips = vec![*id];
|
||||
}
|
||||
}
|
||||
|
||||
for descriptor in &clip_scroll_tree.clip_chains_descriptors {
|
||||
self.clip_chains.insert(
|
||||
ClipId::ClipChain(descriptor.id),
|
||||
HitTestClipChainDescriptor {
|
||||
parent: descriptor.parent.map(|id| ClipId::ClipChain(id)),
|
||||
clips: descriptor.clips.clone(),
|
||||
}
|
||||
);
|
||||
let clip_chain = self.clip_chains.get_mut(descriptor.index.0).unwrap();
|
||||
clip_chain.parent = clip_scroll_tree.get_clip_chain(descriptor.index).parent_index;
|
||||
clip_chain.clips = descriptor.clips.clone();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_point_clipped_in_for_clip_chain(
|
||||
&self,
|
||||
point: WorldPoint,
|
||||
chain_id: &ClipId,
|
||||
clip_chain_index: ClipChainIndex,
|
||||
test: &mut HitTest
|
||||
) -> bool {
|
||||
if let Some(result) = test.clip_chain_cache.get(&chain_id) {
|
||||
return *result;
|
||||
if let Some(result) = test.get_from_clip_chain_cache(clip_chain_index) {
|
||||
return result;
|
||||
}
|
||||
|
||||
let descriptor = &self.clip_chains[&chain_id];
|
||||
let descriptor = &self.clip_chains[clip_chain_index.0];
|
||||
let parent_clipped_in = match descriptor.parent {
|
||||
None => true,
|
||||
Some(ref parent) => self.is_point_clipped_in_for_clip_chain(point, parent, test),
|
||||
Some(parent) => self.is_point_clipped_in_for_clip_chain(point, parent, test),
|
||||
};
|
||||
|
||||
if !parent_clipped_in {
|
||||
test.clip_chain_cache.insert(*chain_id, false);
|
||||
test.set_in_clip_chain_cache(clip_chain_index, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
for clip_node in &descriptor.clips {
|
||||
if !self.is_point_clipped_in_for_node(point, clip_node, test) {
|
||||
test.clip_chain_cache.insert(*chain_id, false);
|
||||
test.set_in_clip_chain_cache(clip_chain_index, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
test.clip_chain_cache.insert(*chain_id, true);
|
||||
test.set_in_clip_chain_cache(clip_chain_index, true);
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -197,7 +211,9 @@ impl HitTester {
|
|||
|
||||
let mut result = HitTestResult::default();
|
||||
for &HitTestingRun(ref items, ref clip_and_scroll) in self.runs.iter().rev() {
|
||||
let scroll_node = &self.nodes[&clip_and_scroll.scroll_node_id];
|
||||
let scroll_node_id = clip_and_scroll.scroll_node_id;
|
||||
let scroll_node = &self.nodes[&scroll_node_id];
|
||||
let pipeline_id = scroll_node_id.pipeline_id();
|
||||
match (test.pipeline_id, clip_and_scroll.scroll_node_id.pipeline_id()) {
|
||||
(Some(id), node_id) if node_id != id => continue,
|
||||
_ => {},
|
||||
|
@ -215,12 +231,11 @@ impl HitTester {
|
|||
continue;
|
||||
}
|
||||
|
||||
let clip_id = &clip_and_scroll.clip_node_id();
|
||||
let clip_chain_index = clip_and_scroll.clip_chain_index;
|
||||
clipped_in |=
|
||||
self.is_point_clipped_in_for_clip_chain(point, clip_chain_index, &mut test);
|
||||
if !clipped_in {
|
||||
clipped_in = self.is_point_clipped_in_for_clip_chain(point, clip_id, &mut test);
|
||||
if !clipped_in {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// We need to trigger a lookup against the root reference frame here, because
|
||||
|
@ -228,7 +243,7 @@ impl HitTester {
|
|||
// hierarchy. If we don't have a valid point for this test, we are likely
|
||||
// in a situation where the reference frame has an univertible transform, but the
|
||||
// item's clip does not.
|
||||
let root_reference_frame = ClipId::root_reference_frame(clip_id.pipeline_id());
|
||||
let root_reference_frame = ClipId::root_reference_frame(pipeline_id);
|
||||
if !self.is_point_clipped_in_for_node(point, &root_reference_frame, &mut test) {
|
||||
continue;
|
||||
}
|
||||
|
@ -238,7 +253,7 @@ impl HitTester {
|
|||
};
|
||||
|
||||
result.items.push(HitTestItem {
|
||||
pipeline: clip_and_scroll.clip_node_id().pipeline_id(),
|
||||
pipeline: pipeline_id,
|
||||
tag: item.tag,
|
||||
point_in_viewport,
|
||||
point_relative_to_item: point_in_layer - item.rect.origin.to_vector(),
|
||||
|
@ -259,7 +274,7 @@ fn get_regions_for_clip_scroll_node(
|
|||
clip_store: &ClipStore
|
||||
) -> Vec<HitTestRegion> {
|
||||
let clips = match node.node_type {
|
||||
NodeType::Clip(ref handle) => clip_store.get(handle).clips(),
|
||||
NodeType::Clip{ ref handle, .. } => clip_store.get(handle).clips(),
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
|
||||
|
@ -280,7 +295,7 @@ pub struct HitTest {
|
|||
point: WorldPoint,
|
||||
flags: HitTestFlags,
|
||||
node_cache: FastHashMap<ClipId, Option<LayerPoint>>,
|
||||
clip_chain_cache: FastHashMap<ClipId, bool>,
|
||||
clip_chain_cache: Vec<Option<bool>>,
|
||||
}
|
||||
|
||||
impl HitTest {
|
||||
|
@ -294,10 +309,25 @@ impl HitTest {
|
|||
point,
|
||||
flags,
|
||||
node_cache: FastHashMap::default(),
|
||||
clip_chain_cache: FastHashMap::default(),
|
||||
clip_chain_cache: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_from_clip_chain_cache(&mut self, index: ClipChainIndex) -> Option<bool> {
|
||||
if index.0 >= self.clip_chain_cache.len() {
|
||||
None
|
||||
} else {
|
||||
self.clip_chain_cache[index.0]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_in_clip_chain_cache(&mut self, index: ClipChainIndex, value: bool) {
|
||||
if index.0 >= self.clip_chain_cache.len() {
|
||||
self.clip_chain_cache.resize(index.0 + 1, None);
|
||||
}
|
||||
self.clip_chain_cache[index.0] = Some(value);
|
||||
}
|
||||
|
||||
pub fn get_absolute_point(&self, hit_tester: &HitTester) -> WorldPoint {
|
||||
if !self.flags.contains(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT) {
|
||||
return self.point;
|
||||
|
|
|
@ -44,7 +44,11 @@ pub struct CacheTextureId(pub usize);
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct RenderPassIndex(pub usize);
|
||||
pub struct SavedTargetIndex(pub usize);
|
||||
|
||||
impl SavedTargetIndex {
|
||||
pub const PENDING: Self = SavedTargetIndex(!0);
|
||||
}
|
||||
|
||||
// Represents the source for a texture.
|
||||
// These are passed from throughout the
|
||||
|
@ -61,10 +65,7 @@ pub enum SourceTexture {
|
|||
External(ExternalImageData),
|
||||
CacheA8,
|
||||
CacheRGBA8,
|
||||
// XXX Remove this once RenderTaskCacheA8 is used.
|
||||
#[allow(dead_code)]
|
||||
RenderTaskCacheA8(RenderPassIndex),
|
||||
RenderTaskCacheRGBA8(RenderPassIndex),
|
||||
RenderTaskCache(SavedTargetIndex),
|
||||
}
|
||||
|
||||
pub const ORTHO_NEAR_PLANE: f32 = -1000000.0;
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ColorF, ClipAndScrollInfo, FilterOp, MixBlendMode};
|
||||
use api::{DeviceIntPoint, DeviceIntRect, LayerToWorldScale, PipelineId};
|
||||
use api::{BoxShadowClipMode, LayerPoint, LayerRect, LayerVector2D, Shadow};
|
||||
use api::{ClipId, PremultipliedColorF};
|
||||
use api::{BoxShadowClipMode, ClipId, ColorF, DeviceIntPoint, DeviceIntRect, FilterOp, LayerPoint};
|
||||
use api::{LayerRect, LayerToWorldScale, LayerVector2D, MixBlendMode, PipelineId};
|
||||
use api::{PremultipliedColorF, Shadow};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
|
||||
use frame_builder::{FrameContext, FrameState, PictureState};
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use gpu_types::{BrushImageKind, PictureType};
|
||||
use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect};
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskCacheKey};
|
||||
use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
|
||||
use resource_cache::CacheItem;
|
||||
|
@ -230,7 +230,7 @@ impl PicturePrimitive {
|
|||
pub fn add_primitive(
|
||||
&mut self,
|
||||
prim_index: PrimitiveIndex,
|
||||
clip_and_scroll: ClipAndScrollInfo
|
||||
clip_and_scroll: ScrollNodeAndClipChain
|
||||
) {
|
||||
if let Some(ref mut run) = self.runs.last_mut() {
|
||||
if run.clip_and_scroll == clip_and_scroll &&
|
||||
|
@ -368,7 +368,7 @@ impl PicturePrimitive {
|
|||
}
|
||||
Some(PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color))) => {
|
||||
let rect = (prim_local_rect.translate(&-offset) * content_scale).round().to_i32();
|
||||
let picture_task = RenderTask::new_picture(
|
||||
let mut picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, rect.size),
|
||||
prim_index,
|
||||
RenderTargetKind::Color,
|
||||
|
@ -378,6 +378,7 @@ impl PicturePrimitive {
|
|||
pic_state_for_children.tasks,
|
||||
PictureType::Image,
|
||||
);
|
||||
picture_task.mark_for_saving();
|
||||
|
||||
let blur_std_deviation = blur_radius * frame_context.device_pixel_scale.0;
|
||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||
|
@ -601,7 +602,7 @@ impl PicturePrimitive {
|
|||
match composite_mode {
|
||||
Some(PictureCompositeMode::Filter(FilterOp::ColorMatrix(m))) => {
|
||||
for i in 0..5 {
|
||||
request.push([m[i], m[i+5], m[i+10], m[i+15]]);
|
||||
request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
|
||||
}
|
||||
}
|
||||
Some(PictureCompositeMode::Filter(filter)) => {
|
||||
|
|
|
@ -2,25 +2,24 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipAndScrollInfo, ClipMode};
|
||||
use api::{ColorF, DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch};
|
||||
use api::{ComplexClipRegion, ExtendMode, FontRenderMode};
|
||||
use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipId, ClipMode, ColorF, ComplexClipRegion};
|
||||
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode};
|
||||
use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
|
||||
use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation};
|
||||
use api::{LineStyle, PremultipliedColorF};
|
||||
use api::{WorldToLayerTransform, YuvColorSpace, YuvFormat};
|
||||
use api::{LineStyle, PremultipliedColorF, WorldToLayerTransform, YuvColorSpace, YuvFormat};
|
||||
use border::{BorderCornerInstance, BorderEdgeKind};
|
||||
use clip_scroll_tree::{CoordinateSystemId};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||
use clip_scroll_node::ClipScrollNode;
|
||||
use clip::{ClipSource, ClipSourcesHandle};
|
||||
use clip::{ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipSource};
|
||||
use clip::{ClipSourcesHandle, ClipWorkItem};
|
||||
use frame_builder::{FrameContext, FrameState, PictureContext, PictureState, PrimitiveRunContext};
|
||||
use glyph_rasterizer::{FontInstance, FontTransform};
|
||||
use gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest,
|
||||
ToGpuBlocks};
|
||||
use gpu_types::{ClipChainRectIndex};
|
||||
use picture::{PictureKind, PicturePrimitive};
|
||||
use render_task::{BlitSource, ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipWorkItem};
|
||||
use render_task::{RenderTask, RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId};
|
||||
use render_task::{BlitSource, RenderTask, RenderTaskCacheKey, RenderTaskCacheKeyKind};
|
||||
use render_task::RenderTaskId;
|
||||
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||
use resource_cache::{CacheItem, ImageProperties, ImageRequest, ResourceCache};
|
||||
use segment::SegmentBuilder;
|
||||
|
@ -32,11 +31,23 @@ use util::recycle_vec;
|
|||
|
||||
const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ScrollNodeAndClipChain {
|
||||
pub scroll_node_id: ClipId,
|
||||
pub clip_chain_index: ClipChainIndex,
|
||||
}
|
||||
|
||||
impl ScrollNodeAndClipChain {
|
||||
pub fn new(scroll_node_id: ClipId, clip_chain_index: ClipChainIndex) -> ScrollNodeAndClipChain {
|
||||
ScrollNodeAndClipChain { scroll_node_id, clip_chain_index }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PrimitiveRun {
|
||||
pub base_prim_index: PrimitiveIndex,
|
||||
pub count: usize,
|
||||
pub clip_and_scroll: ClipAndScrollInfo,
|
||||
pub clip_and_scroll: ScrollNodeAndClipChain,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -112,11 +123,9 @@ pub struct PrimitiveIndex(pub usize);
|
|||
pub enum PrimitiveKind {
|
||||
TextRun,
|
||||
Image,
|
||||
YuvImage,
|
||||
Border,
|
||||
AlignedGradient,
|
||||
AngleGradient,
|
||||
RadialGradient,
|
||||
Picture,
|
||||
Brush,
|
||||
}
|
||||
|
@ -195,6 +204,22 @@ pub enum BrushKind {
|
|||
current_epoch: Epoch,
|
||||
alpha_type: AlphaType,
|
||||
},
|
||||
YuvImage {
|
||||
yuv_key: [ImageKey; 3],
|
||||
format: YuvFormat,
|
||||
color_space: YuvColorSpace,
|
||||
image_rendering: ImageRendering,
|
||||
},
|
||||
RadialGradient {
|
||||
stops_range: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
stops_handle: GpuCacheHandle,
|
||||
start_center: LayerPoint,
|
||||
end_center: LayerPoint,
|
||||
start_radius: f32,
|
||||
end_radius: f32,
|
||||
ratio_xy: f32,
|
||||
}
|
||||
}
|
||||
|
||||
impl BrushKind {
|
||||
|
@ -202,7 +227,9 @@ impl BrushKind {
|
|||
match *self {
|
||||
BrushKind::Solid { .. } |
|
||||
BrushKind::Picture |
|
||||
BrushKind::Image { .. } => true,
|
||||
BrushKind::Image { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } => true,
|
||||
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Clear |
|
||||
|
@ -284,7 +311,8 @@ impl BrushPrimitive {
|
|||
// has to match VECS_PER_SPECIFIC_BRUSH
|
||||
match self.kind {
|
||||
BrushKind::Picture |
|
||||
BrushKind::Image { .. } => {
|
||||
BrushKind::Image { .. } |
|
||||
BrushKind::YuvImage { .. } => {
|
||||
}
|
||||
BrushKind::Solid { color } => {
|
||||
request.push(color.premultiplied());
|
||||
|
@ -331,6 +359,20 @@ impl BrushPrimitive {
|
|||
0.0,
|
||||
]);
|
||||
}
|
||||
BrushKind::RadialGradient { start_center, end_center, start_radius, end_radius, ratio_xy, extend_mode, .. } => {
|
||||
request.push([
|
||||
start_center.x,
|
||||
start_center.y,
|
||||
end_center.x,
|
||||
end_center.y,
|
||||
]);
|
||||
request.push([
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
pack_as_float(extend_mode as u32),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -377,24 +419,6 @@ impl ToGpuBlocks for ImagePrimitiveCpu {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct YuvImagePrimitiveCpu {
|
||||
pub yuv_key: [ImageKey; 3],
|
||||
pub format: YuvFormat,
|
||||
pub color_space: YuvColorSpace,
|
||||
|
||||
pub image_rendering: ImageRendering,
|
||||
|
||||
// TODO(gw): Generate on demand
|
||||
pub gpu_block: GpuBlockData,
|
||||
}
|
||||
|
||||
impl ToGpuBlocks for YuvImagePrimitiveCpu {
|
||||
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
|
||||
request.push(self.gpu_block);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BorderPrimitiveCpu {
|
||||
pub corner_instances: [BorderCornerInstance; 4],
|
||||
|
@ -631,27 +655,6 @@ impl<'a> GradientGpuBlockBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RadialGradientPrimitiveCpu {
|
||||
pub stops_range: ItemRange<GradientStop>,
|
||||
pub extend_mode: ExtendMode,
|
||||
pub gpu_data_count: i32,
|
||||
pub gpu_blocks: [GpuBlockData; 3],
|
||||
}
|
||||
|
||||
impl RadialGradientPrimitiveCpu {
|
||||
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(false, &mut request);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextRunPrimitiveCpu {
|
||||
pub font: FontInstance,
|
||||
|
@ -933,11 +936,9 @@ impl ClipData {
|
|||
pub enum PrimitiveContainer {
|
||||
TextRun(TextRunPrimitiveCpu),
|
||||
Image(ImagePrimitiveCpu),
|
||||
YuvImage(YuvImagePrimitiveCpu),
|
||||
Border(BorderPrimitiveCpu),
|
||||
AlignedGradient(GradientPrimitiveCpu),
|
||||
AngleGradient(GradientPrimitiveCpu),
|
||||
RadialGradient(RadialGradientPrimitiveCpu),
|
||||
Picture(PicturePrimitive),
|
||||
Brush(BrushPrimitive),
|
||||
}
|
||||
|
@ -948,9 +949,7 @@ pub struct PrimitiveStore {
|
|||
pub cpu_text_runs: Vec<TextRunPrimitiveCpu>,
|
||||
pub cpu_pictures: Vec<PicturePrimitive>,
|
||||
pub cpu_images: Vec<ImagePrimitiveCpu>,
|
||||
pub cpu_yuv_images: Vec<YuvImagePrimitiveCpu>,
|
||||
pub cpu_gradients: Vec<GradientPrimitiveCpu>,
|
||||
pub cpu_radial_gradients: Vec<RadialGradientPrimitiveCpu>,
|
||||
pub cpu_metadata: Vec<PrimitiveMetadata>,
|
||||
pub cpu_borders: Vec<BorderPrimitiveCpu>,
|
||||
}
|
||||
|
@ -963,9 +962,7 @@ impl PrimitiveStore {
|
|||
cpu_text_runs: Vec::new(),
|
||||
cpu_pictures: Vec::new(),
|
||||
cpu_images: Vec::new(),
|
||||
cpu_yuv_images: Vec::new(),
|
||||
cpu_gradients: Vec::new(),
|
||||
cpu_radial_gradients: Vec::new(),
|
||||
cpu_borders: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -977,9 +974,7 @@ impl PrimitiveStore {
|
|||
cpu_text_runs: recycle_vec(self.cpu_text_runs),
|
||||
cpu_pictures: recycle_vec(self.cpu_pictures),
|
||||
cpu_images: recycle_vec(self.cpu_images),
|
||||
cpu_yuv_images: recycle_vec(self.cpu_yuv_images),
|
||||
cpu_gradients: recycle_vec(self.cpu_gradients),
|
||||
cpu_radial_gradients: recycle_vec(self.cpu_radial_gradients),
|
||||
cpu_borders: recycle_vec(self.cpu_borders),
|
||||
}
|
||||
}
|
||||
|
@ -1018,6 +1013,8 @@ impl PrimitiveStore {
|
|||
BrushKind::Mask { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Line { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
|
||||
BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Picture => {
|
||||
// TODO(gw): This is not currently used. In the future
|
||||
// we should detect opaque pictures.
|
||||
|
@ -1069,17 +1066,6 @@ impl PrimitiveStore {
|
|||
self.cpu_images.push(image_cpu);
|
||||
metadata
|
||||
}
|
||||
PrimitiveContainer::YuvImage(image_cpu) => {
|
||||
let metadata = PrimitiveMetadata {
|
||||
opacity: PrimitiveOpacity::opaque(),
|
||||
prim_kind: PrimitiveKind::YuvImage,
|
||||
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_yuv_images.len()),
|
||||
..base_metadata
|
||||
};
|
||||
|
||||
self.cpu_yuv_images.push(image_cpu);
|
||||
metadata
|
||||
}
|
||||
PrimitiveContainer::Border(border_cpu) => {
|
||||
let metadata = PrimitiveMetadata {
|
||||
opacity: PrimitiveOpacity::translucent(),
|
||||
|
@ -1114,18 +1100,6 @@ impl PrimitiveStore {
|
|||
self.cpu_gradients.push(gradient_cpu);
|
||||
metadata
|
||||
}
|
||||
PrimitiveContainer::RadialGradient(radial_gradient_cpu) => {
|
||||
let metadata = PrimitiveMetadata {
|
||||
// TODO: calculate if the gradient is actually opaque
|
||||
opacity: PrimitiveOpacity::translucent(),
|
||||
prim_kind: PrimitiveKind::RadialGradient,
|
||||
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_radial_gradients.len()),
|
||||
..base_metadata
|
||||
};
|
||||
|
||||
self.cpu_radial_gradients.push(radial_gradient_cpu);
|
||||
metadata
|
||||
}
|
||||
};
|
||||
|
||||
self.cpu_metadata.push(metadata);
|
||||
|
@ -1293,22 +1267,6 @@ impl PrimitiveStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrimitiveKind::YuvImage => {
|
||||
let image_cpu = &mut self.cpu_yuv_images[metadata.cpu_prim_index.0];
|
||||
|
||||
let channel_num = image_cpu.format.get_plane_num();
|
||||
debug_assert!(channel_num <= 3);
|
||||
for channel in 0 .. channel_num {
|
||||
frame_state.resource_cache.request_image(
|
||||
ImageRequest {
|
||||
key: image_cpu.yuv_key[channel],
|
||||
rendering: image_cpu.image_rendering,
|
||||
tile: None,
|
||||
},
|
||||
frame_state.gpu_cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
PrimitiveKind::Brush => {
|
||||
let brush = &mut self.cpu_brushes[metadata.cpu_prim_index.0];
|
||||
|
||||
|
@ -1332,6 +1290,32 @@ impl PrimitiveStore {
|
|||
frame_state.gpu_cache,
|
||||
);
|
||||
}
|
||||
BrushKind::YuvImage { format, yuv_key, image_rendering, .. } => {
|
||||
let channel_num = format.get_plane_num();
|
||||
debug_assert!(channel_num <= 3);
|
||||
for channel in 0 .. channel_num {
|
||||
frame_state.resource_cache.request_image(
|
||||
ImageRequest {
|
||||
key: yuv_key[channel],
|
||||
rendering: image_rendering,
|
||||
tile: None,
|
||||
},
|
||||
frame_state.gpu_cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
BrushKind::RadialGradient { ref mut stops_handle, stops_range, .. } => {
|
||||
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(
|
||||
false,
|
||||
&mut request,
|
||||
);
|
||||
}
|
||||
}
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Solid { .. } |
|
||||
BrushKind::Clear |
|
||||
|
@ -1340,8 +1324,7 @@ impl PrimitiveStore {
|
|||
}
|
||||
}
|
||||
PrimitiveKind::AlignedGradient |
|
||||
PrimitiveKind::AngleGradient |
|
||||
PrimitiveKind::RadialGradient => {}
|
||||
PrimitiveKind::AngleGradient => {}
|
||||
}
|
||||
|
||||
// Mark this GPU resource as required for this frame.
|
||||
|
@ -1359,10 +1342,6 @@ impl PrimitiveStore {
|
|||
let image = &self.cpu_images[metadata.cpu_prim_index.0];
|
||||
image.write_gpu_blocks(request);
|
||||
}
|
||||
PrimitiveKind::YuvImage => {
|
||||
let yuv_image = &self.cpu_yuv_images[metadata.cpu_prim_index.0];
|
||||
yuv_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(
|
||||
|
@ -1377,13 +1356,6 @@ impl PrimitiveStore {
|
|||
request,
|
||||
);
|
||||
}
|
||||
PrimitiveKind::RadialGradient => {
|
||||
let gradient = &self.cpu_radial_gradients[metadata.cpu_prim_index.0];
|
||||
gradient.build_gpu_blocks_for_angle_radial(
|
||||
pic_context.display_list,
|
||||
request,
|
||||
);
|
||||
}
|
||||
PrimitiveKind::TextRun => {
|
||||
let text = &self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||
text.write_gpu_blocks(&mut request);
|
||||
|
@ -1634,12 +1606,9 @@ impl PrimitiveStore {
|
|||
}
|
||||
};
|
||||
|
||||
let mut combined_outer_rect = match prim_run_context.clip_chain {
|
||||
Some(ref chain) => prim_screen_rect.intersection(&chain.combined_outer_screen_rect),
|
||||
None => Some(prim_screen_rect),
|
||||
};
|
||||
|
||||
let clip_chain = prim_run_context.clip_chain.map_or(None, |x| x.nodes.clone());
|
||||
let mut combined_outer_rect =
|
||||
prim_screen_rect.intersection(&prim_run_context.clip_chain.combined_outer_screen_rect);
|
||||
let clip_chain = prim_run_context.clip_chain.nodes.clone();
|
||||
|
||||
let prim_coordinate_system_id = prim_run_context.scroll_node.coordinate_system_id;
|
||||
let transform = &prim_run_context.scroll_node.world_content_transform;
|
||||
|
@ -1860,12 +1829,8 @@ impl PrimitiveStore {
|
|||
frame_context.device_pixel_scale,
|
||||
);
|
||||
|
||||
let clip_bounds = match prim_run_context.clip_chain {
|
||||
Some(ref node) => node.combined_outer_screen_rect,
|
||||
None => frame_context.screen_rect,
|
||||
};
|
||||
metadata.screen_rect = screen_bounding_rect
|
||||
.intersection(&clip_bounds)
|
||||
.intersection(&prim_run_context.clip_chain.combined_outer_screen_rect)
|
||||
.map(|clipped| {
|
||||
ScreenRect {
|
||||
clipped,
|
||||
|
@ -1935,7 +1900,7 @@ impl PrimitiveStore {
|
|||
.nodes[&run.clip_and_scroll.scroll_node_id];
|
||||
let clip_chain = frame_context
|
||||
.clip_scroll_tree
|
||||
.get_clip_chain(&run.clip_and_scroll.clip_node_id());
|
||||
.get_clip_chain(run.clip_and_scroll.clip_chain_index);
|
||||
|
||||
if pic_context.perform_culling {
|
||||
if !scroll_node.invertible {
|
||||
|
@ -1943,16 +1908,12 @@ impl PrimitiveStore {
|
|||
continue;
|
||||
}
|
||||
|
||||
match clip_chain {
|
||||
Some(ref chain) if chain.combined_outer_screen_rect.is_empty() => {
|
||||
debug!("{:?} {:?}: clipped out", run.base_prim_index, pic_context.pipeline_id);
|
||||
continue;
|
||||
}
|
||||
_ => {},
|
||||
if clip_chain.combined_outer_screen_rect.is_empty() {
|
||||
debug!("{:?} {:?}: clipped out", run.base_prim_index, pic_context.pipeline_id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let parent_relative_transform = pic_context
|
||||
.inv_world_transform
|
||||
.map(|inv_parent| {
|
||||
|
@ -2082,14 +2043,9 @@ fn convert_clip_chain_to_clip_vector(
|
|||
|
||||
fn get_local_clip_rect_for_nodes(
|
||||
scroll_node: &ClipScrollNode,
|
||||
clip_chain: Option<&ClipChain>,
|
||||
clip_chain: &ClipChain,
|
||||
) -> Option<LayerRect> {
|
||||
let clip_chain_nodes = match clip_chain {
|
||||
Some(ref clip_chain) => clip_chain.nodes.clone(),
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let local_rect = ClipChainNodeIter { current: clip_chain_nodes }.fold(
|
||||
let local_rect = ClipChainNodeIter { current: clip_chain.nodes.clone() }.fold(
|
||||
None,
|
||||
|combined_local_clip_rect: Option<LayerRect>, node| {
|
||||
if node.work_item.coordinate_system_id != scroll_node.coordinate_system_id {
|
||||
|
|
|
@ -300,6 +300,9 @@ impl ProfileCounter for AverageTimeProfileCounter {
|
|||
pub struct FrameProfileCounters {
|
||||
pub total_primitives: IntProfileCounter,
|
||||
pub visible_primitives: IntProfileCounter,
|
||||
pub targets_used: IntProfileCounter,
|
||||
pub targets_changed: IntProfileCounter,
|
||||
pub targets_created: IntProfileCounter,
|
||||
}
|
||||
|
||||
impl FrameProfileCounters {
|
||||
|
@ -307,8 +310,16 @@ impl FrameProfileCounters {
|
|||
FrameProfileCounters {
|
||||
total_primitives: IntProfileCounter::new("Total Primitives"),
|
||||
visible_primitives: IntProfileCounter::new("Visible Primitives"),
|
||||
targets_used: IntProfileCounter::new("Used targets"),
|
||||
targets_changed: IntProfileCounter::new("Changed targets"),
|
||||
targets_created: IntProfileCounter::new("Created targets"),
|
||||
}
|
||||
}
|
||||
pub fn reset_targets(&mut self) {
|
||||
self.targets_used.reset();
|
||||
self.targets_changed.reset();
|
||||
self.targets_created.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -840,7 +851,7 @@ impl Profiler {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_gpu_cache_bar(
|
||||
fn draw_bar(
|
||||
&mut self,
|
||||
label: &str,
|
||||
label_color: ColorU,
|
||||
|
@ -898,9 +909,9 @@ impl Profiler {
|
|||
value: counters.allocated_rows.value * MAX_VERTEX_TEXTURE_WIDTH,
|
||||
};
|
||||
|
||||
let rect0 = self.draw_gpu_cache_bar(
|
||||
let rect0 = self.draw_bar(
|
||||
&format!("GPU cache rows ({}):", counters.allocated_rows.value),
|
||||
ColorU::new(255, 255, 255, 255),
|
||||
ColorU::new(0xFF, 0xFF, 0xFF, 0xFF),
|
||||
&[
|
||||
(color_updated, &counters.updated_rows),
|
||||
(color_free, &counters.allocated_rows),
|
||||
|
@ -908,14 +919,53 @@ impl Profiler {
|
|||
debug_renderer,
|
||||
);
|
||||
|
||||
let rect1 = self.draw_gpu_cache_bar(
|
||||
let rect1 = self.draw_bar(
|
||||
"GPU cache blocks",
|
||||
ColorU::new(255, 255, 0, 255),
|
||||
ColorU::new(0xFF, 0xFF, 0, 0xFF),
|
||||
&[
|
||||
(color_updated, &counters.updated_blocks),
|
||||
(color_saved, &requested_blocks),
|
||||
(color_free, &counters.allocated_blocks),
|
||||
(ColorU::new(0, 0, 0, 255), &total_blocks),
|
||||
(ColorU::new(0, 0, 0, 0xFF), &total_blocks),
|
||||
],
|
||||
debug_renderer,
|
||||
);
|
||||
|
||||
let total_rect = rect0.union(&rect1).inflate(10.0, 10.0);
|
||||
debug_renderer.add_quad(
|
||||
total_rect.origin.x,
|
||||
total_rect.origin.y,
|
||||
total_rect.origin.x + total_rect.size.width,
|
||||
total_rect.origin.y + total_rect.size.height,
|
||||
ColorF::new(0.1, 0.1, 0.1, 0.8).into(),
|
||||
ColorF::new(0.2, 0.2, 0.2, 0.8).into(),
|
||||
);
|
||||
|
||||
self.draw_state.y_left = total_rect.origin.y + total_rect.size.height + 30.0;
|
||||
}
|
||||
|
||||
fn draw_frame_bars(
|
||||
&mut self,
|
||||
counters: &FrameProfileCounters,
|
||||
debug_renderer: &mut DebugRenderer,
|
||||
) {
|
||||
let rect0 = self.draw_bar(
|
||||
&format!("primitives ({}):", counters.total_primitives.value),
|
||||
ColorU::new(0xFF, 0xFF, 0xFF, 0xFF),
|
||||
&[
|
||||
(ColorU::new(0, 0, 0xFF, 0xFF), &counters.visible_primitives),
|
||||
(ColorU::new(0, 0, 0, 0xFF), &counters.total_primitives),
|
||||
],
|
||||
debug_renderer,
|
||||
);
|
||||
|
||||
let rect1 = self.draw_bar(
|
||||
&format!("GPU targets ({}):", &counters.targets_used.value),
|
||||
ColorU::new(0xFF, 0xFF, 0, 0xFF),
|
||||
&[
|
||||
(ColorU::new(0, 0, 0xFF, 0xFF), &counters.targets_created),
|
||||
(ColorU::new(0xFF, 0, 0, 0xFF), &counters.targets_changed),
|
||||
(ColorU::new(0, 0xFF, 0, 0xFF), &counters.targets_used),
|
||||
],
|
||||
debug_renderer,
|
||||
);
|
||||
|
@ -1017,15 +1067,7 @@ impl Profiler {
|
|||
);
|
||||
|
||||
for frame_profile in frame_profiles {
|
||||
Profiler::draw_counters(
|
||||
&[
|
||||
&frame_profile.total_primitives,
|
||||
&frame_profile.visible_primitives,
|
||||
],
|
||||
debug_renderer,
|
||||
true,
|
||||
&mut self.draw_state
|
||||
);
|
||||
self.draw_frame_bars(frame_profile, debug_renderer);
|
||||
}
|
||||
|
||||
Profiler::draw_counters(
|
||||
|
|
|
@ -2,22 +2,21 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{ImageDescriptor, ImageFormat, LayerRect, PremultipliedColorF};
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, ImageDescriptor, ImageFormat};
|
||||
use api::PremultipliedColorF;
|
||||
use box_shadow::BoxShadowCacheKey;
|
||||
use clip::{ClipSourcesWeakHandle};
|
||||
use clip::ClipWorkItem;
|
||||
use clip_scroll_tree::CoordinateSystemId;
|
||||
use device::TextureFilter;
|
||||
use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipScrollNodeIndex, PictureType};
|
||||
use internal_types::{FastHashMap, RenderPassIndex, SourceTexture};
|
||||
use gpu_types::PictureType;
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::ContentOrigin;
|
||||
use prim_store::{PrimitiveIndex, ImageCacheKey};
|
||||
#[cfg(feature = "debugger")]
|
||||
use print_tree::{PrintTreePrinter};
|
||||
use resource_cache::CacheItem;
|
||||
use std::{cmp, ops, usize, f32, i32};
|
||||
use std::rc::Rc;
|
||||
use texture_cache::{TextureCache, TextureCacheHandle};
|
||||
use tiling::{RenderPass, RenderTargetIndex};
|
||||
use tiling::{RenderTargetKind};
|
||||
|
@ -43,91 +42,7 @@ pub struct RenderTaskAddress(pub u32);
|
|||
pub struct RenderTaskTree {
|
||||
pub tasks: Vec<RenderTask>,
|
||||
pub task_data: Vec<RenderTaskData>,
|
||||
}
|
||||
|
||||
pub type ClipChainNodeRef = Option<Rc<ClipChainNode>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClipChainNode {
|
||||
pub work_item: ClipWorkItem,
|
||||
pub local_clip_rect: LayerRect,
|
||||
pub screen_outer_rect: DeviceIntRect,
|
||||
pub screen_inner_rect: DeviceIntRect,
|
||||
pub prev: ClipChainNodeRef,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClipChain {
|
||||
pub combined_outer_screen_rect: DeviceIntRect,
|
||||
pub combined_inner_screen_rect: DeviceIntRect,
|
||||
pub nodes: ClipChainNodeRef,
|
||||
}
|
||||
|
||||
impl ClipChain {
|
||||
pub fn empty(screen_rect: &DeviceIntRect) -> ClipChain {
|
||||
ClipChain {
|
||||
combined_inner_screen_rect: *screen_rect,
|
||||
combined_outer_screen_rect: *screen_rect,
|
||||
nodes: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_added_node(
|
||||
&self,
|
||||
work_item: ClipWorkItem,
|
||||
local_clip_rect: LayerRect,
|
||||
screen_outer_rect: DeviceIntRect,
|
||||
screen_inner_rect: DeviceIntRect,
|
||||
) -> ClipChain {
|
||||
let new_node = ClipChainNode {
|
||||
work_item,
|
||||
local_clip_rect,
|
||||
screen_outer_rect,
|
||||
screen_inner_rect,
|
||||
prev: None,
|
||||
};
|
||||
|
||||
let mut new_chain = self.clone();
|
||||
new_chain.add_node(new_node);
|
||||
new_chain
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, mut new_node: ClipChainNode) {
|
||||
new_node.prev = self.nodes.clone();
|
||||
|
||||
// If this clip's outer rectangle is completely enclosed by the clip
|
||||
// chain's inner rectangle, then the only clip that matters from this point
|
||||
// on is this clip. We can disconnect this clip from the parent clip chain.
|
||||
if self.combined_inner_screen_rect.contains_rect(&new_node.screen_outer_rect) {
|
||||
new_node.prev = None;
|
||||
}
|
||||
|
||||
self.combined_outer_screen_rect =
|
||||
self.combined_outer_screen_rect.intersection(&new_node.screen_outer_rect)
|
||||
.unwrap_or_else(DeviceIntRect::zero);
|
||||
self.combined_inner_screen_rect =
|
||||
self.combined_inner_screen_rect.intersection(&new_node.screen_inner_rect)
|
||||
.unwrap_or_else(DeviceIntRect::zero);
|
||||
|
||||
self.nodes = Some(Rc::new(new_node));
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipChainNodeIter {
|
||||
pub current: ClipChainNodeRef,
|
||||
}
|
||||
|
||||
impl Iterator for ClipChainNodeIter {
|
||||
type Item = Rc<ClipChainNode>;
|
||||
|
||||
fn next(&mut self) -> ClipChainNodeRef {
|
||||
let previous = self.current.clone();
|
||||
self.current = match self.current {
|
||||
Some(ref item) => item.prev.clone(),
|
||||
None => return None,
|
||||
};
|
||||
previous
|
||||
}
|
||||
next_saved: SavedTargetIndex,
|
||||
}
|
||||
|
||||
impl RenderTaskTree {
|
||||
|
@ -135,6 +50,7 @@ impl RenderTaskTree {
|
|||
RenderTaskTree {
|
||||
tasks: Vec::new(),
|
||||
task_data: Vec::new(),
|
||||
next_saved: SavedTargetIndex(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,10 +111,16 @@ impl RenderTaskTree {
|
|||
}
|
||||
|
||||
pub fn build(&mut self) {
|
||||
for task in &mut self.tasks {
|
||||
for task in &self.tasks {
|
||||
self.task_data.push(task.write_task_data());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_target(&mut self) -> SavedTargetIndex {
|
||||
let id = self.next_saved;
|
||||
self.next_saved.0 += 1;
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<RenderTaskId> for RenderTaskTree {
|
||||
|
@ -223,15 +145,6 @@ pub enum RenderTaskLocation {
|
|||
TextureCache(SourceTexture, i32, DeviceIntRect),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ClipWorkItem {
|
||||
pub scroll_node_data_index: ClipScrollNodeIndex,
|
||||
pub clip_sources: ClipSourcesWeakHandle,
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -331,7 +244,7 @@ pub struct RenderTask {
|
|||
pub children: Vec<RenderTaskId>,
|
||||
pub kind: RenderTaskKind,
|
||||
pub clear_mode: ClearMode,
|
||||
pub pass_index: Option<RenderPassIndex>,
|
||||
pub saved_index: Option<SavedTargetIndex>,
|
||||
}
|
||||
|
||||
impl RenderTask {
|
||||
|
@ -356,7 +269,7 @@ impl RenderTask {
|
|||
pic_type,
|
||||
}),
|
||||
clear_mode,
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +279,7 @@ impl RenderTask {
|
|||
location: RenderTaskLocation::Dynamic(None, screen_rect.size),
|
||||
kind: RenderTaskKind::Readback(screen_rect),
|
||||
clear_mode: ClearMode::Transparent,
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,7 +305,7 @@ impl RenderTask {
|
|||
source,
|
||||
}),
|
||||
clear_mode: ClearMode::Transparent,
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,7 +313,7 @@ impl RenderTask {
|
|||
outer_rect: DeviceIntRect,
|
||||
clips: Vec<ClipWorkItem>,
|
||||
prim_coordinate_system_id: CoordinateSystemId,
|
||||
) -> RenderTask {
|
||||
) -> Self {
|
||||
RenderTask {
|
||||
children: Vec::new(),
|
||||
location: RenderTaskLocation::Dynamic(None, outer_rect.size),
|
||||
|
@ -410,7 +323,7 @@ impl RenderTask {
|
|||
coordinate_system_id: prim_coordinate_system_id,
|
||||
}),
|
||||
clear_mode: ClearMode::One,
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -473,7 +386,7 @@ impl RenderTask {
|
|||
scale_factor,
|
||||
}),
|
||||
clear_mode,
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
};
|
||||
|
||||
let blur_task_v_id = render_tasks.add(blur_task_v);
|
||||
|
@ -488,7 +401,7 @@ impl RenderTask {
|
|||
scale_factor,
|
||||
}),
|
||||
clear_mode,
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
};
|
||||
|
||||
(blur_task_h, scale_factor)
|
||||
|
@ -507,7 +420,7 @@ impl RenderTask {
|
|||
RenderTargetKind::Color => ClearMode::Transparent,
|
||||
RenderTargetKind::Alpha => ClearMode::One,
|
||||
},
|
||||
pass_index: None,
|
||||
saved_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -674,7 +587,6 @@ impl RenderTask {
|
|||
RenderTaskKind::HorizontalBlur(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Blit(..) => false,
|
||||
|
||||
RenderTaskKind::CacheMask(..) => true,
|
||||
}
|
||||
}
|
||||
|
@ -723,6 +635,19 @@ impl RenderTask {
|
|||
pt.end_level();
|
||||
true
|
||||
}
|
||||
|
||||
/// Mark this render task for keeping the results alive up until the end of the frame.
|
||||
pub fn mark_for_saving(&mut self) {
|
||||
match self.location {
|
||||
RenderTaskLocation::Fixed(..) |
|
||||
RenderTaskLocation::Dynamic(..) => {
|
||||
self.saved_index = Some(SavedTargetIndex::PENDING);
|
||||
}
|
||||
RenderTaskLocation::TextureCache(..) => {
|
||||
panic!("Unable to mark a permanently cached task for saving!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
|
|
|
@ -40,15 +40,15 @@ use glyph_rasterizer::GlyphFormat;
|
|||
use gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList};
|
||||
use gpu_types::PrimitiveInstance;
|
||||
use internal_types::{SourceTexture, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
|
||||
use internal_types::{CacheTextureId, FastHashMap, RenderedDocument, ResultMsg, TextureUpdateOp};
|
||||
use internal_types::{DebugOutput, RenderPassIndex, RenderTargetInfo, TextureUpdateList, TextureUpdateSource};
|
||||
use internal_types::{CacheTextureId, DebugOutput, FastHashMap, RenderedDocument, ResultMsg};
|
||||
use internal_types::{TextureUpdateList, TextureUpdateOp, TextureUpdateSource};
|
||||
use internal_types::{RenderTargetInfo, SavedTargetIndex};
|
||||
use picture::ContentOrigin;
|
||||
use prim_store::DeferredResolve;
|
||||
use profiler::{BackendProfileCounters, Profiler};
|
||||
use profiler::{BackendProfileCounters, FrameProfileCounters, Profiler};
|
||||
use profiler::{GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
|
||||
use query::{GpuProfiler, GpuTimer};
|
||||
use rayon::Configuration as ThreadPoolConfig;
|
||||
use rayon::ThreadPool;
|
||||
use rayon::{ThreadPool, ThreadPoolBuilder};
|
||||
use record::ApiRecordingReceiver;
|
||||
use render_backend::RenderBackend;
|
||||
use render_task::{RenderTaskKind, RenderTaskTree};
|
||||
|
@ -83,6 +83,14 @@ const GPU_CACHE_RESIZE_TEST: bool = false;
|
|||
/// Number of GPU blocks per UV rectangle provided for an image.
|
||||
pub const BLOCKS_PER_UV_RECT: usize = 2;
|
||||
|
||||
const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
|
||||
label: "B_RadialGradient",
|
||||
color: debug_colors::LIGHTPINK,
|
||||
};
|
||||
const GPU_TAG_BRUSH_YUV_IMAGE: GpuProfileTag = GpuProfileTag {
|
||||
label: "B_YuvImage",
|
||||
color: debug_colors::DARKGREEN,
|
||||
};
|
||||
const GPU_TAG_BRUSH_MIXBLEND: GpuProfileTag = GpuProfileTag {
|
||||
label: "B_MixBlend",
|
||||
color: debug_colors::MAGENTA,
|
||||
|
@ -131,10 +139,6 @@ const GPU_TAG_PRIM_IMAGE: GpuProfileTag = GpuProfileTag {
|
|||
label: "Image",
|
||||
color: debug_colors::GREEN,
|
||||
};
|
||||
const GPU_TAG_PRIM_YUV_IMAGE: GpuProfileTag = GpuProfileTag {
|
||||
label: "YuvImage",
|
||||
color: debug_colors::DARKGREEN,
|
||||
};
|
||||
const GPU_TAG_PRIM_HW_COMPOSITE: GpuProfileTag = GpuProfileTag {
|
||||
label: "HwComposite",
|
||||
color: debug_colors::DODGERBLUE,
|
||||
|
@ -155,10 +159,6 @@ const GPU_TAG_PRIM_ANGLE_GRADIENT: GpuProfileTag = GpuProfileTag {
|
|||
label: "AngleGradient",
|
||||
color: debug_colors::POWDERBLUE,
|
||||
};
|
||||
const GPU_TAG_PRIM_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag {
|
||||
label: "RadialGradient",
|
||||
color: debug_colors::LIGHTPINK,
|
||||
};
|
||||
const GPU_TAG_PRIM_BORDER_CORNER: GpuProfileTag = GpuProfileTag {
|
||||
label: "BorderCorner",
|
||||
color: debug_colors::DARKSLATEGREY,
|
||||
|
@ -200,10 +200,8 @@ impl TransformBatchKind {
|
|||
ImageBufferKind::TextureExternal => "Image (External)",
|
||||
ImageBufferKind::Texture2DArray => "Image (Array)",
|
||||
},
|
||||
TransformBatchKind::YuvImage(..) => "YuvImage",
|
||||
TransformBatchKind::AlignedGradient => "AlignedGradient",
|
||||
TransformBatchKind::AngleGradient => "AngleGradient",
|
||||
TransformBatchKind::RadialGradient => "RadialGradient",
|
||||
TransformBatchKind::BorderCorner => "BorderCorner",
|
||||
TransformBatchKind::BorderEdge => "BorderEdge",
|
||||
}
|
||||
|
@ -213,12 +211,10 @@ impl TransformBatchKind {
|
|||
match *self {
|
||||
TransformBatchKind::TextRun(..) => GPU_TAG_PRIM_TEXT_RUN,
|
||||
TransformBatchKind::Image(..) => GPU_TAG_PRIM_IMAGE,
|
||||
TransformBatchKind::YuvImage(..) => GPU_TAG_PRIM_YUV_IMAGE,
|
||||
TransformBatchKind::BorderCorner => GPU_TAG_PRIM_BORDER_CORNER,
|
||||
TransformBatchKind::BorderEdge => GPU_TAG_PRIM_BORDER_EDGE,
|
||||
TransformBatchKind::AlignedGradient => GPU_TAG_PRIM_GRADIENT,
|
||||
TransformBatchKind::AngleGradient => GPU_TAG_PRIM_ANGLE_GRADIENT,
|
||||
TransformBatchKind::RadialGradient => GPU_TAG_PRIM_RADIAL_GRADIENT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,6 +233,8 @@ impl BatchKind {
|
|||
BrushBatchKind::Image(..) => "Brush (Image)",
|
||||
BrushBatchKind::Blend => "Brush (Blend)",
|
||||
BrushBatchKind::MixBlend { .. } => "Brush (Composite)",
|
||||
BrushBatchKind::YuvImage(..) => "Brush (YuvImage)",
|
||||
BrushBatchKind::RadialGradient => "Brush (RadialGradient)",
|
||||
}
|
||||
}
|
||||
BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(),
|
||||
|
@ -255,6 +253,8 @@ impl BatchKind {
|
|||
BrushBatchKind::Image(..) => GPU_TAG_BRUSH_IMAGE,
|
||||
BrushBatchKind::Blend => GPU_TAG_BRUSH_BLEND,
|
||||
BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND,
|
||||
BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE,
|
||||
BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT,
|
||||
}
|
||||
}
|
||||
BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(),
|
||||
|
@ -598,7 +598,11 @@ impl CpuProfile {
|
|||
}
|
||||
}
|
||||
|
||||
struct RenderTargetPoolId(usize);
|
||||
struct ActiveTexture {
|
||||
texture: Texture,
|
||||
saved_index: Option<SavedTargetIndex>,
|
||||
is_shared: bool,
|
||||
}
|
||||
|
||||
struct SourceTextureResolver {
|
||||
/// A vector for fast resolves of texture cache IDs to
|
||||
|
@ -620,12 +624,17 @@ struct SourceTextureResolver {
|
|||
dummy_cache_texture: Texture,
|
||||
|
||||
/// The current cache textures.
|
||||
cache_rgba8_texture: Option<Texture>,
|
||||
cache_a8_texture: Option<Texture>,
|
||||
cache_rgba8_texture: Option<ActiveTexture>,
|
||||
cache_a8_texture: Option<ActiveTexture>,
|
||||
|
||||
pass_rgba8_textures: FastHashMap<RenderPassIndex, RenderTargetPoolId>,
|
||||
pass_a8_textures: FastHashMap<RenderPassIndex, RenderTargetPoolId>,
|
||||
/// An alpha texture shared between all passes.
|
||||
//TODO: just use the standard texture saving logic instead.
|
||||
shared_alpha_texture: Option<Texture>,
|
||||
|
||||
/// Saved cache textures that are to be re-used.
|
||||
saved_textures: Vec<Texture>,
|
||||
|
||||
/// General pool of render targets.
|
||||
render_target_pool: Vec<Texture>,
|
||||
}
|
||||
|
||||
|
@ -649,8 +658,8 @@ impl SourceTextureResolver {
|
|||
dummy_cache_texture,
|
||||
cache_a8_texture: None,
|
||||
cache_rgba8_texture: None,
|
||||
pass_rgba8_textures: FastHashMap::default(),
|
||||
pass_a8_textures: FastHashMap::default(),
|
||||
shared_alpha_texture: None,
|
||||
saved_textures: Vec::default(),
|
||||
render_target_pool: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -670,34 +679,47 @@ impl SourceTextureResolver {
|
|||
fn begin_frame(&mut self) {
|
||||
assert!(self.cache_rgba8_texture.is_none());
|
||||
assert!(self.cache_a8_texture.is_none());
|
||||
|
||||
self.pass_rgba8_textures.clear();
|
||||
self.pass_a8_textures.clear();
|
||||
assert!(self.saved_textures.is_empty());
|
||||
}
|
||||
|
||||
fn end_frame(&mut self, pass_index: RenderPassIndex) {
|
||||
fn end_frame(&mut self) {
|
||||
// return the cached targets to the pool
|
||||
self.end_pass(None, None, pass_index)
|
||||
self.end_pass(None, None);
|
||||
// return the global alpha texture
|
||||
self.render_target_pool.extend(self.shared_alpha_texture.take());
|
||||
// return the saved targets as well
|
||||
self.render_target_pool.extend(self.saved_textures.drain(..));
|
||||
}
|
||||
|
||||
fn end_pass(
|
||||
&mut self,
|
||||
a8_texture: Option<Texture>,
|
||||
rgba8_texture: Option<Texture>,
|
||||
pass_index: RenderPassIndex,
|
||||
a8_texture: Option<ActiveTexture>,
|
||||
rgba8_texture: Option<ActiveTexture>,
|
||||
) {
|
||||
// If we have cache textures from previous pass, return them to the pool.
|
||||
// Also assign the pool index of those cache textures to last pass's index because this is
|
||||
// the result of last pass.
|
||||
if let Some(texture) = self.cache_rgba8_texture.take() {
|
||||
self.pass_rgba8_textures.insert(
|
||||
RenderPassIndex(pass_index.0 - 1), RenderTargetPoolId(self.render_target_pool.len()));
|
||||
self.render_target_pool.push(texture);
|
||||
// Note: the order here is important, needs to match the logic in `RenderPass::build()`.
|
||||
if let Some(at) = self.cache_rgba8_texture.take() {
|
||||
assert!(!at.is_shared);
|
||||
if let Some(index) = at.saved_index {
|
||||
assert_eq!(self.saved_textures.len(), index.0);
|
||||
self.saved_textures.push(at.texture);
|
||||
} else {
|
||||
self.render_target_pool.push(at.texture);
|
||||
}
|
||||
}
|
||||
if let Some(texture) = self.cache_a8_texture.take() {
|
||||
self.pass_a8_textures.insert(
|
||||
RenderPassIndex(pass_index.0 - 1), RenderTargetPoolId(self.render_target_pool.len()));
|
||||
self.render_target_pool.push(texture);
|
||||
if let Some(at) = self.cache_a8_texture.take() {
|
||||
if let Some(index) = at.saved_index {
|
||||
assert!(!at.is_shared);
|
||||
assert_eq!(self.saved_textures.len(), index.0);
|
||||
self.saved_textures.push(at.texture);
|
||||
} else if at.is_shared {
|
||||
assert!(self.shared_alpha_texture.is_none());
|
||||
self.shared_alpha_texture = Some(at.texture);
|
||||
} else {
|
||||
self.render_target_pool.push(at.texture);
|
||||
}
|
||||
}
|
||||
|
||||
// We have another pass to process, make these textures available
|
||||
|
@ -711,15 +733,17 @@ impl SourceTextureResolver {
|
|||
match *texture_id {
|
||||
SourceTexture::Invalid => {}
|
||||
SourceTexture::CacheA8 => {
|
||||
let texture = self.cache_a8_texture
|
||||
.as_ref()
|
||||
.unwrap_or(&self.dummy_cache_texture);
|
||||
let texture = match self.cache_a8_texture {
|
||||
Some(ref at) => &at.texture,
|
||||
None => &self.dummy_cache_texture,
|
||||
};
|
||||
device.bind_texture(sampler, texture);
|
||||
}
|
||||
SourceTexture::CacheRGBA8 => {
|
||||
let texture = self.cache_rgba8_texture
|
||||
.as_ref()
|
||||
.unwrap_or(&self.dummy_cache_texture);
|
||||
let texture = match self.cache_rgba8_texture {
|
||||
Some(ref at) => &at.texture,
|
||||
None => &self.dummy_cache_texture,
|
||||
};
|
||||
device.bind_texture(sampler, texture);
|
||||
}
|
||||
SourceTexture::External(external_image) => {
|
||||
|
@ -732,17 +756,9 @@ impl SourceTextureResolver {
|
|||
let texture = &self.cache_texture_map[index.0];
|
||||
device.bind_texture(sampler, texture);
|
||||
}
|
||||
SourceTexture::RenderTaskCacheRGBA8(pass_index) => {
|
||||
let pool_index = self.pass_rgba8_textures
|
||||
.get(&pass_index)
|
||||
.expect("BUG: pass_index doesn't map to pool_index");
|
||||
device.bind_texture(sampler, &self.render_target_pool[pool_index.0])
|
||||
}
|
||||
SourceTexture::RenderTaskCacheA8(pass_index) => {
|
||||
let pool_index = self.pass_a8_textures
|
||||
.get(&pass_index)
|
||||
.expect("BUG: pass_index doesn't map to pool_index");
|
||||
device.bind_texture(sampler, &self.render_target_pool[pool_index.0])
|
||||
SourceTexture::RenderTaskCache(saved_index) => {
|
||||
let texture = &self.saved_textures[saved_index.0];
|
||||
device.bind_texture(sampler, texture)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -754,31 +770,26 @@ impl SourceTextureResolver {
|
|||
match *texture_id {
|
||||
SourceTexture::Invalid => None,
|
||||
SourceTexture::CacheA8 => Some(
|
||||
self.cache_a8_texture
|
||||
.as_ref()
|
||||
.unwrap_or(&self.dummy_cache_texture),
|
||||
match self.cache_a8_texture {
|
||||
Some(ref at) => &at.texture,
|
||||
None => &self.dummy_cache_texture,
|
||||
}
|
||||
),
|
||||
SourceTexture::CacheRGBA8 => Some(
|
||||
self.cache_rgba8_texture
|
||||
.as_ref()
|
||||
.unwrap_or(&self.dummy_cache_texture),
|
||||
match self.cache_rgba8_texture {
|
||||
Some(ref at) => &at.texture,
|
||||
None => &self.dummy_cache_texture,
|
||||
}
|
||||
),
|
||||
SourceTexture::External(..) => {
|
||||
panic!("BUG: External textures cannot be resolved, they can only be bound.");
|
||||
}
|
||||
SourceTexture::TextureCache(index) => Some(&self.cache_texture_map[index.0]),
|
||||
SourceTexture::RenderTaskCacheRGBA8(pass_index) => {
|
||||
let pool_index = self.pass_rgba8_textures
|
||||
.get(&pass_index)
|
||||
.expect("BUG: pass_index doesn't map to pool_index");
|
||||
Some(&self.render_target_pool[pool_index.0])
|
||||
},
|
||||
SourceTexture::RenderTaskCacheA8(pass_index) => {
|
||||
let pool_index = self.pass_a8_textures
|
||||
.get(&pass_index)
|
||||
.expect("BUG: pass_index doesn't map to pool_index");
|
||||
Some(&self.render_target_pool[pool_index.0])
|
||||
},
|
||||
SourceTexture::TextureCache(index) => {
|
||||
Some(&self.cache_texture_map[index.0])
|
||||
}
|
||||
SourceTexture::RenderTaskCache(saved_index) => {
|
||||
Some(&self.saved_textures[saved_index.0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1605,6 +1616,8 @@ pub struct Renderer {
|
|||
brush_image: Vec<Option<BrushShader>>,
|
||||
brush_blend: BrushShader,
|
||||
brush_mix_blend: BrushShader,
|
||||
brush_yuv_image: Vec<Option<BrushShader>>,
|
||||
brush_radial_gradient: BrushShader,
|
||||
|
||||
/// These are "cache clip shaders". These shaders are used to
|
||||
/// draw clip instances into the cached clip mask. The results
|
||||
|
@ -1623,12 +1636,10 @@ pub struct Renderer {
|
|||
ps_text_run: TextShader,
|
||||
ps_text_run_dual_source: TextShader,
|
||||
ps_image: Vec<Option<PrimitiveShader>>,
|
||||
ps_yuv_image: Vec<Option<PrimitiveShader>>,
|
||||
ps_border_corner: PrimitiveShader,
|
||||
ps_border_edge: PrimitiveShader,
|
||||
ps_gradient: PrimitiveShader,
|
||||
ps_angle_gradient: PrimitiveShader,
|
||||
ps_radial_gradient: PrimitiveShader,
|
||||
|
||||
ps_hw_composite: LazilyCompiledShader,
|
||||
ps_split_composite: LazilyCompiledShader,
|
||||
|
@ -1745,6 +1756,7 @@ impl Renderer {
|
|||
let (payload_tx, payload_rx) = try!{ channel::payload_channel() };
|
||||
let (result_tx, result_rx) = channel();
|
||||
let gl_type = gl.get_type();
|
||||
let dithering_feature = ["DITHERING"];
|
||||
|
||||
let debug_server = DebugServer::new(api_tx.clone());
|
||||
|
||||
|
@ -1861,6 +1873,17 @@ impl Renderer {
|
|||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let brush_radial_gradient = try!{
|
||||
BrushShader::new("brush_radial_gradient",
|
||||
&mut device,
|
||||
if options.enable_dithering {
|
||||
&dithering_feature
|
||||
} else {
|
||||
&[]
|
||||
},
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let cs_blur_a8 = try!{
|
||||
LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur),
|
||||
"cs_blur",
|
||||
|
@ -1952,10 +1975,10 @@ impl Renderer {
|
|||
// All yuv_image configuration.
|
||||
let mut yuv_features = Vec::new();
|
||||
let yuv_shader_num = IMAGE_BUFFER_KINDS.len() * YUV_FORMATS.len() * YUV_COLOR_SPACES.len();
|
||||
let mut ps_yuv_image: Vec<Option<PrimitiveShader>> = Vec::new();
|
||||
let mut brush_yuv_image = Vec::new();
|
||||
// PrimitiveShader is not clonable. Use push() to initialize the vec.
|
||||
for _ in 0 .. yuv_shader_num {
|
||||
ps_yuv_image.push(None);
|
||||
brush_yuv_image.push(None);
|
||||
}
|
||||
for buffer_kind in 0 .. IMAGE_BUFFER_KINDS.len() {
|
||||
if IMAGE_BUFFER_KINDS[buffer_kind].has_platform_support(&gl_type) {
|
||||
|
@ -1976,17 +1999,17 @@ impl Renderer {
|
|||
}
|
||||
|
||||
let shader = try!{
|
||||
PrimitiveShader::new("ps_yuv_image",
|
||||
&mut device,
|
||||
&yuv_features,
|
||||
options.precache_shaders)
|
||||
BrushShader::new("brush_yuv_image",
|
||||
&mut device,
|
||||
&yuv_features,
|
||||
options.precache_shaders)
|
||||
};
|
||||
let index = Renderer::get_yuv_shader_index(
|
||||
IMAGE_BUFFER_KINDS[buffer_kind],
|
||||
YUV_FORMATS[format_kind],
|
||||
YUV_COLOR_SPACES[color_space_kind],
|
||||
);
|
||||
ps_yuv_image[index] = Some(shader);
|
||||
brush_yuv_image[index] = Some(shader);
|
||||
yuv_features.clear();
|
||||
}
|
||||
}
|
||||
|
@ -2007,8 +2030,6 @@ impl Renderer {
|
|||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let dithering_feature = ["DITHERING"];
|
||||
|
||||
let ps_gradient = try!{
|
||||
PrimitiveShader::new("ps_gradient",
|
||||
&mut device,
|
||||
|
@ -2031,17 +2052,6 @@ impl Renderer {
|
|||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let ps_radial_gradient = try!{
|
||||
PrimitiveShader::new("ps_radial_gradient",
|
||||
&mut device,
|
||||
if options.enable_dithering {
|
||||
&dithering_feature
|
||||
} else {
|
||||
&[]
|
||||
},
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let ps_hw_composite = try!{
|
||||
LazilyCompiledShader::new(ShaderKind::Primitive,
|
||||
"ps_hardware_composite",
|
||||
|
@ -2215,7 +2225,7 @@ impl Renderer {
|
|||
.workers
|
||||
.take()
|
||||
.unwrap_or_else(|| {
|
||||
let worker_config = ThreadPoolConfig::new()
|
||||
let worker = ThreadPoolBuilder::new()
|
||||
.thread_name(|idx|{ format!("WRWorker#{}", idx) })
|
||||
.start_handler(move |idx| {
|
||||
register_thread_with_profiler(format!("WRWorker#{}", idx));
|
||||
|
@ -2227,8 +2237,9 @@ impl Renderer {
|
|||
if let Some(ref thread_listener) = *thread_listener_for_rayon_end {
|
||||
thread_listener.thread_stopped(&format!("WRWorker#{}", idx));
|
||||
}
|
||||
});
|
||||
Arc::new(ThreadPool::new(worker_config).unwrap())
|
||||
})
|
||||
.build();
|
||||
Arc::new(worker.unwrap())
|
||||
});
|
||||
let enable_render_on_scroll = options.enable_render_on_scroll;
|
||||
|
||||
|
@ -2290,18 +2301,18 @@ impl Renderer {
|
|||
brush_image,
|
||||
brush_blend,
|
||||
brush_mix_blend,
|
||||
brush_yuv_image,
|
||||
brush_radial_gradient,
|
||||
cs_clip_rectangle,
|
||||
cs_clip_border,
|
||||
cs_clip_image,
|
||||
ps_text_run,
|
||||
ps_text_run_dual_source,
|
||||
ps_image,
|
||||
ps_yuv_image,
|
||||
ps_border_corner,
|
||||
ps_border_edge,
|
||||
ps_gradient,
|
||||
ps_angle_gradient,
|
||||
ps_radial_gradient,
|
||||
ps_hw_composite,
|
||||
ps_split_composite,
|
||||
debug: debug_renderer,
|
||||
|
@ -2873,18 +2884,13 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
// Re-use whatever targets possible from the pool, before
|
||||
// they get changed/re-allocated by the rendered frames.
|
||||
for doc_with_id in &mut active_documents {
|
||||
self.prepare_tile_frame(&mut doc_with_id.1.frame);
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
self.texture_resolver.external_images.extend(
|
||||
self.owned_external_images.iter().map(|(key, value)| (*key, value.clone()))
|
||||
);
|
||||
|
||||
for &mut (_, RenderedDocument { ref mut frame, .. }) in &mut active_documents {
|
||||
frame.profile_counters.reset_targets();
|
||||
self.prepare_gpu_cache(frame);
|
||||
assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id);
|
||||
|
||||
|
@ -3257,6 +3263,29 @@ impl Renderer {
|
|||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
BrushBatchKind::RadialGradient => {
|
||||
self.brush_radial_gradient.bind(
|
||||
&mut self.device,
|
||||
key.blend_mode,
|
||||
projection,
|
||||
0,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
BrushBatchKind::YuvImage(image_buffer_kind, format, color_space) => {
|
||||
let shader_index =
|
||||
Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space);
|
||||
self.brush_yuv_image[shader_index]
|
||||
.as_mut()
|
||||
.expect("Unsupported YUV shader kind")
|
||||
.bind(
|
||||
&mut self.device,
|
||||
key.blend_mode,
|
||||
projection,
|
||||
0,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
BatchKind::Transformable(transform_kind, batch_kind) => match batch_kind {
|
||||
|
@ -3275,20 +3304,6 @@ impl Renderer {
|
|||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
TransformBatchKind::YuvImage(image_buffer_kind, format, color_space) => {
|
||||
let shader_index =
|
||||
Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space);
|
||||
self.ps_yuv_image[shader_index]
|
||||
.as_mut()
|
||||
.expect("Unsupported YUV shader kind")
|
||||
.bind(
|
||||
&mut self.device,
|
||||
transform_kind,
|
||||
projection,
|
||||
0,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
TransformBatchKind::BorderCorner => {
|
||||
self.ps_border_corner.bind(
|
||||
&mut self.device,
|
||||
|
@ -3325,15 +3340,6 @@ impl Renderer {
|
|||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
TransformBatchKind::RadialGradient => {
|
||||
self.ps_radial_gradient.bind(
|
||||
&mut self.device,
|
||||
transform_kind,
|
||||
projection,
|
||||
0,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -4250,47 +4256,52 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn prepare_target_list<T: RenderTarget>(
|
||||
fn allocate_target_texture<T: RenderTarget>(
|
||||
&mut self,
|
||||
list: &mut RenderTargetList<T>,
|
||||
perfect_only: bool,
|
||||
) {
|
||||
counters: &mut FrameProfileCounters,
|
||||
frame_id: FrameId,
|
||||
) -> Option<ActiveTexture> {
|
||||
debug_assert_ne!(list.max_size, DeviceUintSize::zero());
|
||||
if list.targets.is_empty() {
|
||||
return;
|
||||
return None
|
||||
}
|
||||
let mut texture = if perfect_only {
|
||||
debug_assert!(list.texture.is_none());
|
||||
|
||||
let selector = TargetSelector {
|
||||
size: list.max_size,
|
||||
num_layers: list.targets.len() as _,
|
||||
format: list.format,
|
||||
};
|
||||
let index = self.texture_resolver.render_target_pool
|
||||
counters.targets_used.inc();
|
||||
|
||||
// First, try finding a perfect match
|
||||
let selector = TargetSelector {
|
||||
size: list.max_size,
|
||||
num_layers: list.targets.len() as _,
|
||||
format: list.format,
|
||||
};
|
||||
let mut index = self.texture_resolver.render_target_pool
|
||||
.iter()
|
||||
.position(|texture| {
|
||||
//TODO: re-use a part of a larger target, if available
|
||||
selector == TargetSelector {
|
||||
size: texture.get_dimensions(),
|
||||
num_layers: texture.get_render_target_layer_count(),
|
||||
format: texture.get_format(),
|
||||
}
|
||||
});
|
||||
|
||||
// Next, try at least finding a matching format
|
||||
if index.is_none() {
|
||||
counters.targets_changed.inc();
|
||||
index = self.texture_resolver.render_target_pool
|
||||
.iter()
|
||||
.position(|texture| {
|
||||
selector == TargetSelector {
|
||||
size: texture.get_dimensions(),
|
||||
num_layers: texture.get_render_target_layer_count(),
|
||||
format: texture.get_format(),
|
||||
}
|
||||
});
|
||||
match index {
|
||||
Some(pos) => self.texture_resolver.render_target_pool.swap_remove(pos),
|
||||
None => return,
|
||||
.position(|texture| texture.get_format() == list.format && !texture.used_in_frame(frame_id));
|
||||
}
|
||||
|
||||
let mut texture = match index {
|
||||
Some(pos) => {
|
||||
self.texture_resolver.render_target_pool.swap_remove(pos)
|
||||
}
|
||||
} else {
|
||||
if list.texture.is_some() {
|
||||
list.check_ready();
|
||||
return
|
||||
}
|
||||
let index = self.texture_resolver.render_target_pool
|
||||
.iter()
|
||||
.position(|texture| texture.get_format() == list.format);
|
||||
match index {
|
||||
Some(pos) => self.texture_resolver.render_target_pool.swap_remove(pos),
|
||||
None => self.device.create_texture(TextureTarget::Array, list.format),
|
||||
None => {
|
||||
counters.targets_created.inc();
|
||||
// finally, give up and create a new one
|
||||
self.device.create_texture(TextureTarget::Array, list.format)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4305,34 +4316,19 @@ impl Renderer {
|
|||
list.targets.len() as _,
|
||||
None,
|
||||
);
|
||||
list.texture = Some(texture);
|
||||
list.check_ready();
|
||||
}
|
||||
|
||||
fn prepare_tile_frame(&mut self, frame: &mut Frame) {
|
||||
// Init textures and render targets to match this scene.
|
||||
// First pass grabs all the perfectly matching targets from the pool.
|
||||
for pass in &mut frame.passes {
|
||||
if let RenderPassKind::OffScreen { ref mut alpha, ref mut color, .. } = pass.kind {
|
||||
self.prepare_target_list(alpha, true);
|
||||
self.prepare_target_list(color, true);
|
||||
}
|
||||
}
|
||||
list.check_ready(&texture);
|
||||
Some(ActiveTexture {
|
||||
texture,
|
||||
saved_index: list.saved_index.clone(),
|
||||
is_shared: list.is_shared,
|
||||
})
|
||||
}
|
||||
|
||||
fn bind_frame_data(&mut self, frame: &mut Frame) {
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_SETUP_DATA);
|
||||
self.device.set_device_pixel_ratio(frame.device_pixel_ratio);
|
||||
|
||||
// Some of the textures are already assigned by `prepare_frame`.
|
||||
// Now re-allocate the space for the rest of the target textures.
|
||||
for pass in &mut frame.passes {
|
||||
if let RenderPassKind::OffScreen { ref mut alpha, ref mut color, .. } = pass.kind {
|
||||
self.prepare_target_list(alpha, false);
|
||||
self.prepare_target_list(color, false);
|
||||
}
|
||||
}
|
||||
|
||||
self.node_data_texture.update(&mut self.device, &mut frame.node_data);
|
||||
self.device.bind_texture(TextureSampler::ClipScrollNodes, &self.node_data_texture.texture);
|
||||
|
||||
|
@ -4424,8 +4420,8 @@ impl Renderer {
|
|||
(None, None)
|
||||
}
|
||||
RenderPassKind::OffScreen { ref mut alpha, ref mut color, ref mut texture_cache } => {
|
||||
alpha.check_ready();
|
||||
color.check_ready();
|
||||
let alpha_tex = self.allocate_target_texture(alpha, &mut frame.profile_counters, frame_id);
|
||||
let color_tex = self.allocate_target_texture(color, &mut frame.profile_counters, frame_id);
|
||||
|
||||
// If this frame has already been drawn, then any texture
|
||||
// cache targets have already been updated and can be
|
||||
|
@ -4455,7 +4451,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
self.draw_alpha_target(
|
||||
(alpha.texture.as_ref().unwrap(), target_index as i32),
|
||||
(&alpha_tex.as_ref().unwrap().texture, target_index as i32),
|
||||
target,
|
||||
alpha.max_size,
|
||||
&projection,
|
||||
|
@ -4477,7 +4473,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
self.draw_color_target(
|
||||
Some((color.texture.as_ref().unwrap(), target_index as i32)),
|
||||
Some((&color_tex.as_ref().unwrap().texture, target_index as i32)),
|
||||
target,
|
||||
frame.inner_rect,
|
||||
color.max_size,
|
||||
|
@ -4490,29 +4486,23 @@ impl Renderer {
|
|||
);
|
||||
}
|
||||
|
||||
(alpha.texture.take(), color.texture.take())
|
||||
(alpha_tex, color_tex)
|
||||
}
|
||||
};
|
||||
|
||||
//Note: the `end_pass` will make sure this texture is not recycled this frame
|
||||
if let Some(ActiveTexture { ref texture, is_shared: true, .. }) = cur_alpha {
|
||||
self.device
|
||||
.bind_texture(TextureSampler::SharedCacheA8, texture);
|
||||
}
|
||||
|
||||
self.texture_resolver.end_pass(
|
||||
cur_alpha,
|
||||
cur_color,
|
||||
RenderPassIndex(pass_index),
|
||||
);
|
||||
|
||||
// After completing the first pass, make the A8 target available as an
|
||||
// input to any subsequent passes.
|
||||
if pass_index == 0 {
|
||||
if let Some(shared_alpha_texture) =
|
||||
self.texture_resolver.resolve(&SourceTexture::CacheA8)
|
||||
{
|
||||
self.device
|
||||
.bind_texture(TextureSampler::SharedCacheA8, shared_alpha_texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.texture_resolver.end_frame(RenderPassIndex(frame.passes.len()));
|
||||
self.texture_resolver.end_frame();
|
||||
if let Some(framebuffer_size) = framebuffer_size {
|
||||
self.draw_render_target_debug(framebuffer_size);
|
||||
self.draw_texture_cache_debug(framebuffer_size);
|
||||
|
@ -4750,6 +4740,7 @@ impl Renderer {
|
|||
self.brush_line.deinit(&mut self.device);
|
||||
self.brush_blend.deinit(&mut self.device);
|
||||
self.brush_mix_blend.deinit(&mut self.device);
|
||||
self.brush_radial_gradient.deinit(&mut self.device);
|
||||
self.cs_clip_rectangle.deinit(&mut self.device);
|
||||
self.cs_clip_image.deinit(&mut self.device);
|
||||
self.cs_clip_border.deinit(&mut self.device);
|
||||
|
@ -4765,7 +4756,7 @@ impl Renderer {
|
|||
shader.deinit(&mut self.device);
|
||||
}
|
||||
}
|
||||
for shader in self.ps_yuv_image {
|
||||
for shader in self.brush_yuv_image {
|
||||
if let Some(shader) = shader {
|
||||
shader.deinit(&mut self.device);
|
||||
}
|
||||
|
@ -4777,7 +4768,6 @@ impl Renderer {
|
|||
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_radial_gradient.deinit(&mut self.device);
|
||||
self.ps_hw_composite.deinit(&mut self.device);
|
||||
self.ps_split_composite.deinit(&mut self.device);
|
||||
#[cfg(feature = "capture")]
|
||||
|
|
|
@ -197,10 +197,11 @@ impl FilterOpHelpers for FilterOp {
|
|||
offset.x == 0.0 && offset.y == 0.0 && blur == 0.0
|
||||
},
|
||||
FilterOp::ColorMatrix(matrix) => {
|
||||
matrix == [1.0, 0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0, 0.0]
|
||||
matrix == [1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
0.0, 0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ use clip::{ClipStore};
|
|||
use clip_scroll_tree::{ClipScrollTree};
|
||||
use device::{FrameId, Texture};
|
||||
use gpu_cache::{GpuCache};
|
||||
use gpu_types::{BlurDirection, BlurInstance, BrushInstance, ClipChainRectIndex};
|
||||
use gpu_types::{BlurDirection, BlurInstance, BrushFlags, BrushInstance, ClipChainRectIndex};
|
||||
use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex};
|
||||
use gpu_types::{PrimitiveInstance};
|
||||
use internal_types::{FastHashMap, RenderPassIndex, SourceTexture};
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{PictureKind};
|
||||
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveStore};
|
||||
use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask};
|
||||
|
@ -137,8 +137,8 @@ pub struct RenderTargetList<T> {
|
|||
pub format: ImageFormat,
|
||||
pub max_size: DeviceUintSize,
|
||||
pub targets: Vec<T>,
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub texture: Option<Texture>,
|
||||
pub saved_index: Option<SavedTargetIndex>,
|
||||
pub is_shared: bool,
|
||||
}
|
||||
|
||||
impl<T: RenderTarget> RenderTargetList<T> {
|
||||
|
@ -151,7 +151,8 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
format,
|
||||
max_size: DeviceUintSize::new(MIN_TARGET_SIZE, MIN_TARGET_SIZE),
|
||||
targets: Vec::new(),
|
||||
texture: None,
|
||||
saved_index: None,
|
||||
is_shared: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +162,11 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
gpu_cache: &mut GpuCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
deferred_resolves: &mut Vec<DeferredResolve>,
|
||||
saved_index: Option<SavedTargetIndex>,
|
||||
) {
|
||||
debug_assert_eq!(None, self.saved_index);
|
||||
self.saved_index = saved_index;
|
||||
|
||||
for target in &mut self.targets {
|
||||
target.build(ctx, gpu_cache, render_tasks, deferred_resolves);
|
||||
}
|
||||
|
@ -214,20 +219,13 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
self.targets.iter().any(|target| target.needs_depth())
|
||||
}
|
||||
|
||||
pub fn check_ready(&self) {
|
||||
match self.texture {
|
||||
Some(ref t) => {
|
||||
assert_eq!(t.get_dimensions(), self.max_size);
|
||||
assert_eq!(t.get_format(), self.format);
|
||||
assert_eq!(t.get_render_target_layer_count(), self.targets.len());
|
||||
assert_eq!(t.get_layer_count() as usize, self.targets.len());
|
||||
assert_eq!(t.has_depth(), t.get_rt_info().unwrap().has_depth);
|
||||
assert_eq!(t.has_depth(), self.needs_depth());
|
||||
}
|
||||
None => {
|
||||
assert!(self.targets.is_empty())
|
||||
}
|
||||
}
|
||||
pub fn check_ready(&self, t: &Texture) {
|
||||
assert_eq!(t.get_dimensions(), self.max_size);
|
||||
assert_eq!(t.get_format(), self.format);
|
||||
assert_eq!(t.get_render_target_layer_count(), self.targets.len());
|
||||
assert_eq!(t.get_layer_count() as usize, self.targets.len());
|
||||
assert_eq!(t.has_depth(), t.get_rt_info().unwrap().has_depth);
|
||||
assert_eq!(t.has_depth(), self.needs_depth());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,6 +587,7 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
clip_task_address: RenderTaskAddress(0),
|
||||
z: 0,
|
||||
segment_index: 0,
|
||||
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
user_data: [0; 3],
|
||||
};
|
||||
|
@ -598,6 +597,8 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
BrushKind::Clear |
|
||||
BrushKind::Picture |
|
||||
BrushKind::Line { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::Image { .. } => {
|
||||
unreachable!("bug: unexpected brush here");
|
||||
}
|
||||
|
@ -784,7 +785,6 @@ impl RenderPass {
|
|||
render_tasks: &mut RenderTaskTree,
|
||||
deferred_resolves: &mut Vec<DeferredResolve>,
|
||||
clip_store: &ClipStore,
|
||||
pass_index: RenderPassIndex,
|
||||
) {
|
||||
profile_scope!("RenderPass::build");
|
||||
|
||||
|
@ -792,7 +792,6 @@ impl RenderPass {
|
|||
RenderPassKind::MainFramebuffer(ref mut target) => {
|
||||
for &task_id in &self.tasks {
|
||||
assert_eq!(render_tasks[task_id].target_kind(), RenderTargetKind::Color);
|
||||
render_tasks[task_id].pass_index = Some(pass_index);
|
||||
target.add_task(
|
||||
task_id,
|
||||
ctx,
|
||||
|
@ -805,16 +804,38 @@ impl RenderPass {
|
|||
target.build(ctx, gpu_cache, render_tasks, deferred_resolves);
|
||||
}
|
||||
RenderPassKind::OffScreen { ref mut color, ref mut alpha, ref mut texture_cache } => {
|
||||
let is_shared_alpha = self.tasks.iter().any(|&task_id| {
|
||||
match render_tasks[task_id].kind {
|
||||
RenderTaskKind::CacheMask(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
let saved_color = if self.tasks.iter().any(|&task_id| {
|
||||
let t = &render_tasks[task_id];
|
||||
t.target_kind() == RenderTargetKind::Color && t.saved_index.is_some()
|
||||
}) {
|
||||
Some(render_tasks.save_target())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let saved_alpha = if self.tasks.iter().any(|&task_id| {
|
||||
let t = &render_tasks[task_id];
|
||||
t.target_kind() == RenderTargetKind::Alpha && t.saved_index.is_some()
|
||||
}) {
|
||||
Some(render_tasks.save_target())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Step through each task, adding to batches as appropriate.
|
||||
for &task_id in &self.tasks {
|
||||
let (target_kind, texture_target) = {
|
||||
let task = &mut render_tasks[task_id];
|
||||
task.pass_index = Some(pass_index);
|
||||
let target_kind = task.target_kind();
|
||||
|
||||
// Find a target to assign this task to, or create a new
|
||||
// one if required.
|
||||
match task.location {
|
||||
let (target_kind, texture_target) = match task.location {
|
||||
RenderTaskLocation::TextureCache(texture_id, layer, _) => {
|
||||
// TODO(gw): When we support caching color items, we will
|
||||
// need to calculate that here to get the
|
||||
|
@ -834,7 +855,18 @@ impl RenderPass {
|
|||
|
||||
(target_kind, None)
|
||||
}
|
||||
};
|
||||
|
||||
// Replace the pending saved index with a real one
|
||||
if let Some(index) = task.saved_index {
|
||||
assert_eq!(index, SavedTargetIndex::PENDING);
|
||||
task.saved_index = match target_kind {
|
||||
RenderTargetKind::Color => saved_color,
|
||||
RenderTargetKind::Alpha => saved_alpha,
|
||||
};
|
||||
}
|
||||
|
||||
(target_kind, texture_target)
|
||||
};
|
||||
|
||||
match texture_target {
|
||||
|
@ -869,8 +901,9 @@ impl RenderPass {
|
|||
}
|
||||
}
|
||||
|
||||
color.build(ctx, gpu_cache, render_tasks, deferred_resolves);
|
||||
alpha.build(ctx, gpu_cache, render_tasks, deferred_resolves);
|
||||
color.build(ctx, gpu_cache, render_tasks, deferred_resolves, saved_color);
|
||||
alpha.build(ctx, gpu_cache, render_tasks, deferred_resolves, saved_alpha);
|
||||
alpha.is_shared = is_shared_alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,10 +62,6 @@ const SHADERS: &[Shader] = &[
|
|||
name: "ps_angle_gradient",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_radial_gradient",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_hardware_composite",
|
||||
features: PRIM_FEATURES,
|
||||
|
@ -78,15 +74,15 @@ const SHADERS: &[Shader] = &[
|
|||
name: "ps_image",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_yuv_image",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "ps_text_run",
|
||||
features: PRIM_FEATURES,
|
||||
},
|
||||
// Brush shaders
|
||||
Shader {
|
||||
name: "brush_yuv_image",
|
||||
features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED"],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_mask",
|
||||
features: &[],
|
||||
|
@ -111,6 +107,10 @@ const SHADERS: &[Shader] = &[
|
|||
name: "brush_line",
|
||||
features: &[],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_radial_gradient",
|
||||
features: &[],
|
||||
},
|
||||
];
|
||||
|
||||
const VERSION_STRING: &str = "#version 300 es\n";
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::fmt;
|
|||
use std::marker::PhantomData;
|
||||
use std::path::PathBuf;
|
||||
use std::u32;
|
||||
use {BuiltDisplayList, BuiltDisplayListDescriptor, ClipId, ColorF, DeviceIntPoint, DeviceUintRect};
|
||||
use {BuiltDisplayList, BuiltDisplayListDescriptor, ColorF, DeviceIntPoint, DeviceUintRect};
|
||||
use {DeviceUintSize, ExternalScrollId, FontInstanceKey, FontInstanceOptions};
|
||||
use {FontInstancePlatformOptions, FontKey, FontVariation, GlyphDimensions, GlyphKey, ImageData};
|
||||
use {ImageDescriptor, ImageKey, ItemTag, LayoutPoint, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
|
@ -254,7 +254,7 @@ impl Transaction {
|
|||
pub fn scroll_node_with_id(
|
||||
&mut self,
|
||||
origin: LayoutPoint,
|
||||
id: ScrollNodeIdType,
|
||||
id: ExternalScrollId,
|
||||
clamp: ScrollClamping,
|
||||
) {
|
||||
self.ops.push(DocumentMsg::ScrollNodeWithId(origin, id, clamp));
|
||||
|
@ -384,37 +384,13 @@ pub enum DocumentMsg {
|
|||
device_pixel_ratio: f32,
|
||||
},
|
||||
Scroll(ScrollLocation, WorldPoint, ScrollEventPhase),
|
||||
ScrollNodeWithId(LayoutPoint, ScrollNodeIdType, ScrollClamping),
|
||||
ScrollNodeWithId(LayoutPoint, ExternalScrollId, ScrollClamping),
|
||||
TickScrollingBounce,
|
||||
GetScrollNodeState(MsgSender<Vec<ScrollNodeState>>),
|
||||
GenerateFrame,
|
||||
UpdateDynamicProperties(DynamicProperties),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ScrollNodeIdType {
|
||||
ExternalScrollId(ExternalScrollId),
|
||||
ClipId(ClipId),
|
||||
}
|
||||
|
||||
impl From<ExternalScrollId> for ScrollNodeIdType {
|
||||
fn from(id: ExternalScrollId) -> Self {
|
||||
ScrollNodeIdType::ExternalScrollId(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ClipId> for ScrollNodeIdType {
|
||||
fn from(id: ClipId) -> Self {
|
||||
ScrollNodeIdType::ClipId(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ClipId> for ScrollNodeIdType {
|
||||
fn from(id: &'a ClipId) -> Self {
|
||||
ScrollNodeIdType::ClipId(*id)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DocumentMsg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
|
|
|
@ -601,9 +601,9 @@ impl YuvFormat {
|
|||
|
||||
pub fn get_feature_string(&self) -> &'static str {
|
||||
match *self {
|
||||
YuvFormat::NV12 => "NV12",
|
||||
YuvFormat::PlanarYCbCr => "",
|
||||
YuvFormat::InterleavedYCbCr => "INTERLEAVED_Y_CB_CR",
|
||||
YuvFormat::NV12 => "YUV_NV12",
|
||||
YuvFormat::PlanarYCbCr => "YUV_PLANAR",
|
||||
YuvFormat::InterleavedYCbCr => "YUV_INTERLEAVED",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -649,6 +649,22 @@ impl LocalClip {
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clip_by(&self, rect: &LayoutRect) -> LocalClip {
|
||||
match *self {
|
||||
LocalClip::Rect(clip_rect) => {
|
||||
LocalClip::Rect(
|
||||
clip_rect.intersection(rect).unwrap_or(LayoutRect::zero())
|
||||
)
|
||||
}
|
||||
LocalClip::RoundedRect(clip_rect, complex) => {
|
||||
LocalClip::RoundedRect(
|
||||
clip_rect.intersection(rect).unwrap_or(LayoutRect::zero()),
|
||||
complex,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
|
@ -5,7 +5,7 @@ authors = ["The Mozilla Project Developers"]
|
|||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
rayon = "0.8"
|
||||
rayon = "1"
|
||||
thread_profiler = "0.1.1"
|
||||
euclid = "0.16"
|
||||
app_units = "0.6"
|
||||
|
|
|
@ -1 +1 @@
|
|||
4af31b8aa79d5a1f3c0242dea6be4876c71075c5
|
||||
e8d2ffb404a85651fe08a6d09abbece9bd2b9182
|
||||
|
|
|
@ -502,7 +502,7 @@ impl Wrench {
|
|||
&mut self,
|
||||
frame_number: u32,
|
||||
display_lists: Vec<(PipelineId, LayerSize, BuiltDisplayList)>,
|
||||
scroll_offsets: &HashMap<ClipId, LayerPoint>,
|
||||
scroll_offsets: &HashMap<ExternalScrollId, LayerPoint>,
|
||||
) {
|
||||
let root_background_color = Some(ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
|
@ -523,7 +523,7 @@ impl Wrench {
|
|||
|
||||
let mut txn = Transaction::new();
|
||||
for (id, offset) in scroll_offsets {
|
||||
txn.scroll_node_with_id(*offset, id.into(), ScrollClamping::NoClamping);
|
||||
txn.scroll_node_with_id(*offset, *id, ScrollClamping::NoClamping);
|
||||
}
|
||||
// TODO(nical) - Wrench does not notify frames when there was scrolling
|
||||
// in the transaction (See RenderNotifier implementations). If we don't
|
||||
|
|
|
@ -193,7 +193,7 @@ pub struct YamlFrameReader {
|
|||
|
||||
/// A HashMap of offsets which specify what scroll offsets particular
|
||||
/// scroll layers should be initialized with.
|
||||
scroll_offsets: HashMap<ClipId, LayerPoint>,
|
||||
scroll_offsets: HashMap<ExternalScrollId, LayerPoint>,
|
||||
|
||||
image_map: HashMap<(PathBuf, Option<i64>), (ImageKey, LayoutSize)>,
|
||||
|
||||
|
@ -1273,7 +1273,12 @@ impl YamlFrameReader {
|
|||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
) {
|
||||
let full_clip = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
// A very large number (but safely far away from finite limits of f32)
|
||||
let big_number = 1.0e30;
|
||||
// A rect that should in practical terms serve as a no-op for clipping
|
||||
let full_clip = LayoutRect::new(
|
||||
LayoutPoint::new(-big_number / 2.0, -big_number / 2.0),
|
||||
LayoutSize::new(big_number, big_number));
|
||||
|
||||
for item in yaml.as_vec().unwrap() {
|
||||
// an explicit type can be skipped with some shorthand
|
||||
|
@ -1362,7 +1367,12 @@ impl YamlFrameReader {
|
|||
let complex_clips = self.to_complex_clip_regions(&yaml["complex"]);
|
||||
let image_mask = self.to_image_mask(&yaml["image-mask"], wrench);
|
||||
|
||||
let external_id = numeric_id.map(|id| ExternalScrollId(id as u64, dl.pipeline_id));
|
||||
let external_id = yaml["scroll-offset"].as_point().map(|size| {
|
||||
let id = ExternalScrollId((self.scroll_offsets.len() + 1) as u64, dl.pipeline_id);
|
||||
self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y));
|
||||
id
|
||||
});
|
||||
|
||||
let real_id = dl.define_scroll_frame(
|
||||
external_id,
|
||||
content_rect,
|
||||
|
@ -1375,10 +1385,6 @@ impl YamlFrameReader {
|
|||
self.clip_id_map.insert(numeric_id, real_id);
|
||||
}
|
||||
|
||||
if let Some(size) = yaml["scroll-offset"].as_point() {
|
||||
self.scroll_offsets.insert(real_id, LayerPoint::new(size.x, size.y));
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
|
@ -1542,9 +1548,8 @@ impl YamlFrameReader {
|
|||
|
||||
if is_root {
|
||||
if let Some(size) = yaml["scroll-offset"].as_point() {
|
||||
let id = ClipId::root_scroll_node(dl.pipeline_id);
|
||||
self.scroll_offsets
|
||||
.insert(id, LayerPoint::new(size.x, size.y));
|
||||
let external_id = ExternalScrollId(0, dl.pipeline_id);
|
||||
self.scroll_offsets.insert(external_id, LayerPoint::new(size.x, size.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче