mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 22:05:44 +00:00
Bug 1443807 - Update webrender to commit 5cb71f0f23719795e7c89417d91a7abad8ac20e9. r=jrmuizel
MozReview-Commit-ID: 9JzKooI2sJ2 --HG-- extra : rebase_source : 2762c00c95aa40dcd9d27ef1c5efa66494b8a90b
This commit is contained in:
parent
f177bf9d3d
commit
faa816e22a
@ -13,12 +13,18 @@ varying vec2 vLocalPos;
|
||||
varying vec3 vUv;
|
||||
flat varying vec4 vUvBounds;
|
||||
flat varying vec4 vColor;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
flat varying vec2 vSelect;
|
||||
#endif
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
#define IMAGE_SOURCE_COLOR 0
|
||||
#define IMAGE_SOURCE_ALPHA 1
|
||||
#define IMAGE_SOURCE_MASK_FROM_COLOR 2
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
#define IMAGE_SOURCE_COLOR 0
|
||||
#define IMAGE_SOURCE_ALPHA 1
|
||||
#define IMAGE_SOURCE_MASK_FROM_COLOR 2
|
||||
#endif
|
||||
|
||||
void brush_vs(
|
||||
VertexInfo vi,
|
||||
@ -53,6 +59,7 @@ void brush_vs(
|
||||
max(uv0, uv1) - vec2(0.5)
|
||||
) / texture_size.xyxy;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
switch (user_data.y) {
|
||||
case IMAGE_SOURCE_COLOR:
|
||||
vSelect = vec2(0.0, 0.0);
|
||||
@ -65,7 +72,6 @@ void brush_vs(
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
vLocalPos = vi.local_pos;
|
||||
#endif
|
||||
}
|
||||
@ -76,11 +82,12 @@ vec4 brush_fs() {
|
||||
vec2 uv = clamp(vUv.xy, vUvBounds.xy, vUvBounds.zw);
|
||||
|
||||
vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vUv.z));
|
||||
vec4 mask = mix(texel.rrrr, texel.aaaa, vSelect.x);
|
||||
vec4 color = mix(texel, vColor * mask, vSelect.y);
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
color *= init_transform_fs(vLocalPos);
|
||||
vec4 mask = mix(texel.rrrr, texel.aaaa, vSelect.x);
|
||||
vec4 color = mix(texel, vColor * mask, vSelect.y) * init_transform_fs(vLocalPos);
|
||||
#else
|
||||
vec4 color = texel;
|
||||
#endif
|
||||
|
||||
return color;
|
||||
|
@ -1,114 +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/. */
|
||||
|
||||
#define VECS_PER_SPECIFIC_BRUSH 1
|
||||
|
||||
#include shared,prim_shared,brush
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
varying vec2 vLocalPos;
|
||||
#endif
|
||||
|
||||
varying vec3 vUv;
|
||||
flat varying int vImageKind;
|
||||
flat varying vec4 vUvBounds;
|
||||
flat varying vec4 vUvBounds_NoClamp;
|
||||
flat varying vec4 vParams;
|
||||
flat varying vec4 vColor;
|
||||
|
||||
#define BRUSH_PICTURE_SIMPLE 0
|
||||
#define BRUSH_PICTURE_NINEPATCH 1
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
struct Picture {
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
Picture fetch_picture(int address) {
|
||||
vec4 data = fetch_from_resource_cache_1(address);
|
||||
return Picture(data);
|
||||
}
|
||||
|
||||
void brush_vs(
|
||||
VertexInfo vi,
|
||||
int prim_address,
|
||||
RectWithSize local_rect,
|
||||
ivec3 user_data,
|
||||
PictureTask pic_task
|
||||
) {
|
||||
vImageKind = user_data.y;
|
||||
|
||||
Picture pic = fetch_picture(prim_address);
|
||||
ImageResource res = fetch_image_resource(user_data.x);
|
||||
vec2 texture_size = vec2(textureSize(sColor1, 0).xy);
|
||||
vColor = pic.color;
|
||||
vec2 uv0 = res.uv_rect.p0;
|
||||
vec2 uv1 = res.uv_rect.p1;
|
||||
vec2 src_size = (uv1 - uv0) * res.user_data.x;
|
||||
vUv.z = res.layer;
|
||||
|
||||
// TODO(gw): In the future we'll probably draw these as segments
|
||||
// with the brush shader. When that occurs, we can
|
||||
// modify the UVs for each segment in the VS, and the
|
||||
// FS can become a simple shader that doesn't need
|
||||
// to adjust the UVs.
|
||||
|
||||
switch (vImageKind) {
|
||||
case BRUSH_PICTURE_SIMPLE: {
|
||||
vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
|
||||
vUv.xy = mix(uv0, uv1, f);
|
||||
vUv.xy /= texture_size;
|
||||
break;
|
||||
}
|
||||
case BRUSH_PICTURE_NINEPATCH: {
|
||||
vec2 local_src_size = src_size / uDevicePixelRatio;
|
||||
vUv.xy = (vi.local_pos - local_rect.p0) / local_src_size;
|
||||
vParams.xy = vec2(0.5);
|
||||
vParams.zw = (local_rect.size / local_src_size - 0.5);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
vUv.xy = vec2(0.0);
|
||||
vParams = vec4(0.0);
|
||||
}
|
||||
|
||||
vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
|
||||
vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
vLocalPos = vi.local_pos;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
vec4 brush_fs() {
|
||||
vec2 uv;
|
||||
|
||||
switch (vImageKind) {
|
||||
case BRUSH_PICTURE_SIMPLE: {
|
||||
uv = clamp(vUv.xy, vUvBounds.xy, vUvBounds.zw);
|
||||
break;
|
||||
}
|
||||
case BRUSH_PICTURE_NINEPATCH: {
|
||||
uv = clamp(vUv.xy, vec2(0.0), vParams.xy);
|
||||
uv += max(vec2(0.0), vUv.xy - vParams.zw);
|
||||
uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
|
||||
uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
uv = vec2(0.0);
|
||||
}
|
||||
|
||||
vec4 color = vColor * texture(sColor1, vec3(uv, vUv.z)).r;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
color *= init_transform_fs(vLocalPos);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif
|
@ -53,7 +53,15 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
|
||||
ClipArea area) {
|
||||
vec2 actual_pos = area.screen_origin + aPosition.xy * area.common_data.task_rect.size;
|
||||
|
||||
vec4 node_pos = get_node_pos(actual_pos / uDevicePixelRatio, scroll_node);
|
||||
vec4 node_pos;
|
||||
|
||||
// Select the local position, based on whether we are rasterizing this
|
||||
// clip mask in local- or sccreen-space.
|
||||
if (area.local_space) {
|
||||
node_pos = vec4(actual_pos / uDevicePixelRatio, 0.0, 1.0);
|
||||
} else {
|
||||
node_pos = get_node_pos(actual_pos / uDevicePixelRatio, scroll_node);
|
||||
}
|
||||
|
||||
// compute the point position inside the scroll node, in CSS space
|
||||
vec2 vertex_pos = actual_pos +
|
||||
|
@ -24,7 +24,6 @@ in int aBlurDirection;
|
||||
struct BlurTask {
|
||||
RenderTaskCommonData common_data;
|
||||
float blur_radius;
|
||||
float scale_factor;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
@ -34,7 +33,6 @@ BlurTask fetch_blur_task(int address) {
|
||||
BlurTask task = BlurTask(
|
||||
task_data.common_data,
|
||||
task_data.data1.x,
|
||||
task_data.data1.y,
|
||||
task_data.data2
|
||||
);
|
||||
|
||||
|
82
gfx/webrender/res/cs_clip_box_shadow.glsl
Normal file
82
gfx/webrender/res/cs_clip_box_shadow.glsl
Normal file
@ -0,0 +1,82 @@
|
||||
/* 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,clip_shared
|
||||
|
||||
varying vec3 vPos;
|
||||
varying vec2 vUv;
|
||||
flat varying vec4 vUvBounds;
|
||||
flat varying float vLayer;
|
||||
flat varying vec4 vEdge;
|
||||
flat varying vec4 vUvBounds_NoClamp;
|
||||
flat varying float vClipMode;
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
struct BoxShadowData {
|
||||
vec2 src_rect_size;
|
||||
float clip_mode;
|
||||
RectWithSize dest_rect;
|
||||
};
|
||||
|
||||
BoxShadowData fetch_data(ivec2 address) {
|
||||
vec4 data[2] = fetch_from_resource_cache_2_direct(address);
|
||||
RectWithSize dest_rect = RectWithSize(data[1].xy, data[1].zw);
|
||||
BoxShadowData bs_data = BoxShadowData(data[0].xy, data[0].z, dest_rect);
|
||||
return bs_data;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
ClipMaskInstance cmi = fetch_clip_item();
|
||||
ClipArea area = fetch_clip_area(cmi.render_task_address);
|
||||
ClipScrollNode scroll_node = fetch_clip_scroll_node(cmi.scroll_node_id);
|
||||
BoxShadowData bs_data = fetch_data(cmi.clip_data_address);
|
||||
ImageResource res = fetch_image_resource_direct(cmi.resource_address);
|
||||
|
||||
ClipVertexInfo vi = write_clip_tile_vertex(bs_data.dest_rect,
|
||||
scroll_node,
|
||||
area);
|
||||
|
||||
vLayer = res.layer;
|
||||
vPos = vi.local_pos;
|
||||
vClipMode = bs_data.clip_mode;
|
||||
|
||||
vec2 uv0 = res.uv_rect.p0;
|
||||
vec2 uv1 = res.uv_rect.p1;
|
||||
|
||||
vec2 texture_size = vec2(textureSize(sColor0, 0));
|
||||
vec2 local_pos = vPos.xy / vPos.z;
|
||||
|
||||
vEdge.xy = vec2(0.5);
|
||||
vEdge.zw = (bs_data.dest_rect.size / bs_data.src_rect_size) - vec2(0.5);
|
||||
vUv = (local_pos - bs_data.dest_rect.p0) / bs_data.src_rect_size;
|
||||
|
||||
vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
|
||||
vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
void main(void) {
|
||||
vec2 local_pos = vPos.xy / vPos.z;
|
||||
|
||||
vec2 uv = clamp(vUv.xy, vec2(0.0), vEdge.xy);
|
||||
uv += max(vec2(0.0), vUv.xy - vEdge.zw);
|
||||
|
||||
uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
|
||||
uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
|
||||
|
||||
float in_shadow_rect = point_inside_rect(
|
||||
local_pos,
|
||||
vLocalBounds.xy,
|
||||
vLocalBounds.zw
|
||||
);
|
||||
|
||||
float texel = TEX_SAMPLE(sColor0, vec3(uv, vLayer)).r;
|
||||
|
||||
float alpha = mix(texel, 1.0 - texel, vClipMode);
|
||||
|
||||
oFragColor = vec4(mix(vClipMode, alpha, in_shadow_rect));
|
||||
}
|
||||
#endif
|
@ -86,21 +86,12 @@ uniform HIGHP_SAMPLER_FLOAT sampler2D sRenderTasks;
|
||||
in ivec4 aData0;
|
||||
in ivec4 aData1;
|
||||
|
||||
// Work around Angle bug that forgets to update sampler metadata,
|
||||
// by making the use of those samplers uniform across programs.
|
||||
// https://github.com/servo/webrender/wiki/Driver-issues#texturesize-in-vertex-shaders
|
||||
void markCacheTexturesUsed() {
|
||||
vec2 size = vec2(textureSize(sCacheA8, 0)) + vec2(textureSize(sCacheRGBA8, 0));
|
||||
if (size.x > 1000000.0) {
|
||||
gl_Position = vec4(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// get_fetch_uv is a macro to work around a macOS Intel driver parsing bug.
|
||||
// TODO: convert back to a function once the driver issues are resolved, if ever.
|
||||
// https://github.com/servo/webrender/pull/623
|
||||
// https://github.com/servo/servo/issues/13953
|
||||
#define get_fetch_uv(i, vpi) ivec2(vpi * (i % (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)), i / (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi))
|
||||
// Do the division with unsigned ints because that's more efficient with D3D
|
||||
#define get_fetch_uv(i, vpi) ivec2(int(uint(vpi) * (uint(i) % uint(WR_MAX_VERTEX_TEXTURE_WIDTH/vpi))), int(uint(i) / uint(WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)))
|
||||
|
||||
|
||||
vec4[8] fetch_from_resource_cache_8(int address) {
|
||||
@ -259,7 +250,6 @@ RenderTaskCommonData fetch_render_task_common_data(int index) {
|
||||
|
||||
#define PIC_TYPE_IMAGE 1
|
||||
#define PIC_TYPE_TEXT_SHADOW 2
|
||||
#define PIC_TYPE_BOX_SHADOW 3
|
||||
|
||||
/*
|
||||
The dynamic picture that this brush exists on. Right now, it
|
||||
@ -289,6 +279,7 @@ PictureTask fetch_picture_task(int address) {
|
||||
struct ClipArea {
|
||||
RenderTaskCommonData common_data;
|
||||
vec2 screen_origin;
|
||||
bool local_space;
|
||||
};
|
||||
|
||||
ClipArea fetch_clip_area(int index) {
|
||||
@ -300,11 +291,13 @@ ClipArea fetch_clip_area(int index) {
|
||||
0.0
|
||||
);
|
||||
area.screen_origin = vec2(0.0);
|
||||
area.local_space = false;
|
||||
} else {
|
||||
RenderTaskData task_data = fetch_render_task_data(index);
|
||||
|
||||
area.common_data = task_data.common_data;
|
||||
area.screen_origin = task_data.data1.xy;
|
||||
area.local_space = task_data.data1.z == 0.0;
|
||||
}
|
||||
|
||||
return area;
|
||||
@ -375,8 +368,6 @@ PrimitiveInstance fetch_prim_instance() {
|
||||
pi.user_data1 = aData1.z;
|
||||
pi.user_data2 = aData1.w;
|
||||
|
||||
markCacheTexturesUsed();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
@ -404,8 +395,6 @@ CompositeInstance fetch_composite_instance() {
|
||||
ci.user_data2 = aData1.z;
|
||||
ci.user_data3 = aData1.w;
|
||||
|
||||
markCacheTexturesUsed();
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
@ -822,7 +811,7 @@ float do_clip() {
|
||||
vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
|
||||
// check for the dummy bounds, which are given to the opaque objects
|
||||
return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
|
||||
all(inside) ? texelFetch(sSharedCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
|
||||
all(inside) ? texelFetch(sCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_DITHERING
|
||||
|
@ -16,7 +16,7 @@ use gpu_types::{BrushFlags, BrushInstance, ClipChainRectIndex};
|
||||
use gpu_types::{ClipMaskInstance, ClipScrollNodeIndex};
|
||||
use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveInstance};
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
|
||||
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive};
|
||||
use plane_split::{BspSplitter, Polygon, Splitter};
|
||||
use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
|
||||
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
|
||||
@ -55,7 +55,6 @@ pub enum BrushImageSourceKind {
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum BrushBatchKind {
|
||||
Picture,
|
||||
Solid,
|
||||
Line,
|
||||
Image(ImageBufferKind),
|
||||
@ -522,10 +521,7 @@ impl AlphaBatchBuilder {
|
||||
let pic = &ctx.prim_store.cpu_pictures[pic_metadata.cpu_prim_index.0];
|
||||
let batch = self.batch_list.get_suitable_batch(key, &pic_metadata.screen_rect.as_ref().expect("bug").clipped);
|
||||
|
||||
let render_task_id = match pic.surface {
|
||||
Some(PictureSurface::RenderTask(render_task_id)) => render_task_id,
|
||||
Some(PictureSurface::TextureCache(..)) | None => panic!("BUG: unexpected surface in splitting"),
|
||||
};
|
||||
let render_task_id = pic.surface.expect("BUG: unexpected surface in splitting");
|
||||
let source_task_address = render_tasks.get_task_address(render_task_id);
|
||||
let gpu_address = gpu_handle.as_int(gpu_cache);
|
||||
|
||||
@ -574,7 +570,7 @@ impl AlphaBatchBuilder {
|
||||
// TODO(gw): Support culling on shadow image types.
|
||||
let is_image = match pic.kind {
|
||||
PictureKind::Image { .. } => true,
|
||||
PictureKind::BoxShadow { .. } | PictureKind::TextShadow { .. } => false,
|
||||
PictureKind::TextShadow { .. } => false,
|
||||
};
|
||||
|
||||
if !is_image || metadata.screen_rect.is_some() {
|
||||
@ -801,7 +797,7 @@ impl AlphaBatchBuilder {
|
||||
&ctx.prim_store.cpu_text_runs[prim_metadata.cpu_prim_index.0];
|
||||
let is_shadow = match pic.kind {
|
||||
PictureKind::TextShadow { .. } => true,
|
||||
PictureKind::BoxShadow { .. } | PictureKind::Image { .. } => false,
|
||||
PictureKind::Image { .. } => false,
|
||||
};
|
||||
|
||||
// TODO(gw): It probably makes sense to base this decision on the content
|
||||
@ -894,38 +890,7 @@ impl AlphaBatchBuilder {
|
||||
&ctx.prim_store.cpu_pictures[prim_metadata.cpu_prim_index.0];
|
||||
|
||||
match picture.surface {
|
||||
Some(PictureSurface::TextureCache(ref cache_item)) => {
|
||||
match picture.kind {
|
||||
PictureKind::TextShadow { .. } |
|
||||
PictureKind::Image { .. } => {
|
||||
panic!("BUG: only supported as render tasks for now");
|
||||
}
|
||||
PictureKind::BoxShadow { image_kind, .. } => {
|
||||
let textures = BatchTextures::color(cache_item.texture_id);
|
||||
let kind = BrushBatchKind::Picture;
|
||||
|
||||
self.add_brush_to_batch(
|
||||
&picture.brush,
|
||||
prim_metadata,
|
||||
kind,
|
||||
specified_blend_mode,
|
||||
non_segmented_blend_mode,
|
||||
textures,
|
||||
clip_chain_rect_index,
|
||||
clip_task_address,
|
||||
&task_relative_bounding_rect,
|
||||
prim_cache_address,
|
||||
scroll_id,
|
||||
task_address,
|
||||
transform_kind,
|
||||
z,
|
||||
render_tasks,
|
||||
[cache_item.uv_rect_handle.as_int(gpu_cache), image_kind as i32, 0],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(PictureSurface::RenderTask(cache_task_id)) => {
|
||||
Some(cache_task_id) => {
|
||||
let cache_task_address = render_tasks.get_task_address(cache_task_id);
|
||||
let textures = BatchTextures::render_target_cache();
|
||||
|
||||
@ -959,9 +924,6 @@ impl AlphaBatchBuilder {
|
||||
};
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
}
|
||||
PictureKind::BoxShadow { .. } => {
|
||||
panic!("BUG: should be handled as a texture cache surface");
|
||||
}
|
||||
PictureKind::Image {
|
||||
composite_mode,
|
||||
secondary_render_task_id,
|
||||
@ -1447,9 +1409,6 @@ impl BrushPrimitive {
|
||||
],
|
||||
))
|
||||
}
|
||||
BrushKind::Mask { .. } => {
|
||||
unreachable!("bug: mask brushes not expected in normal alpha pass");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1487,7 +1446,6 @@ impl AlphaBatchHelpers for PrimitiveStore {
|
||||
}
|
||||
}
|
||||
BrushKind::Solid { .. } |
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Line { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } |
|
||||
@ -1599,6 +1557,7 @@ pub struct ClipBatcher {
|
||||
pub images: FastHashMap<SourceTexture, Vec<ClipMaskInstance>>,
|
||||
pub border_clears: Vec<ClipMaskInstance>,
|
||||
pub borders: Vec<ClipMaskInstance>,
|
||||
pub box_shadows: FastHashMap<SourceTexture, Vec<ClipMaskInstance>>,
|
||||
}
|
||||
|
||||
impl ClipBatcher {
|
||||
@ -1608,9 +1567,26 @@ impl ClipBatcher {
|
||||
images: FastHashMap::default(),
|
||||
border_clears: Vec::new(),
|
||||
borders: Vec::new(),
|
||||
box_shadows: FastHashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clip_region(
|
||||
&mut self,
|
||||
task_address: RenderTaskAddress,
|
||||
clip_data_address: GpuCacheAddress,
|
||||
) {
|
||||
let instance = ClipMaskInstance {
|
||||
render_task_address: task_address,
|
||||
scroll_node_data_index: ClipScrollNodeIndex(0),
|
||||
segment: 0,
|
||||
clip_data_address,
|
||||
resource_address: GpuCacheAddress::invalid(),
|
||||
};
|
||||
|
||||
self.rectangles.push(instance);
|
||||
}
|
||||
|
||||
pub fn add(
|
||||
&mut self,
|
||||
task_address: RenderTaskAddress,
|
||||
@ -1659,6 +1635,18 @@ impl ClipBatcher {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ClipSource::BoxShadow(ref info) => {
|
||||
debug_assert_ne!(info.cache_item.texture_id, SourceTexture::Invalid);
|
||||
|
||||
self.box_shadows
|
||||
.entry(info.cache_item.texture_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(ClipMaskInstance {
|
||||
clip_data_address: gpu_address,
|
||||
resource_address: gpu_cache.get_address(&info.cache_item.uv_rect_handle),
|
||||
..instance
|
||||
});
|
||||
}
|
||||
ClipSource::Rectangle(..) => {
|
||||
if work_item.coordinate_system_id != coordinate_system_id {
|
||||
self.rectangles.push(ClipMaskInstance {
|
||||
|
@ -2,19 +2,42 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion, LayerPoint};
|
||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion};
|
||||
use api::{LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D, LayoutSize, LocalClip};
|
||||
use api::PipelineId;
|
||||
use app_units::Au;
|
||||
use api::{DeviceIntSize};
|
||||
use clip::ClipSource;
|
||||
use display_list_flattener::DisplayListFlattener;
|
||||
use gpu_types::BrushImageKind;
|
||||
use gpu_cache::GpuCacheHandle;
|
||||
use prim_store::{BrushKind, BrushPrimitive, PrimitiveContainer};
|
||||
use prim_store::ScrollNodeAndClipChain;
|
||||
use picture::PicturePrimitive;
|
||||
use render_task::MAX_BLUR_STD_DEVIATION;
|
||||
use resource_cache::CacheItem;
|
||||
use util::RectHelpers;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BoxShadowClipSource {
|
||||
// Parameters that define the shadow and are constant.
|
||||
pub shadow_radius: BorderRadius,
|
||||
pub blur_radius: f32,
|
||||
pub clip_mode: BoxShadowClipMode,
|
||||
|
||||
// The current cache key (in device-pixels), and handles
|
||||
// to the cached clip region and blurred texture.
|
||||
pub cache_key: Option<(DeviceIntSize, BoxShadowCacheKey)>,
|
||||
pub cache_item: CacheItem,
|
||||
pub clip_data_handle: GpuCacheHandle,
|
||||
|
||||
// Local-space size of the required render task size.
|
||||
pub shadow_rect_alloc_size: LayerSize,
|
||||
|
||||
// The minimal shadow rect for the parameters above,
|
||||
// used when drawing the shadow rect to be blurred.
|
||||
pub minimal_shadow_rect: LayerRect,
|
||||
|
||||
// Local space rect for the shadow to be drawn or
|
||||
// stretched in the shadow primitive.
|
||||
pub prim_shadow_rect: LayerRect,
|
||||
}
|
||||
|
||||
// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
|
||||
pub const BLUR_SAMPLE_SCALE: f32 = 3.0;
|
||||
|
||||
@ -22,31 +45,25 @@ pub const BLUR_SAMPLE_SCALE: f32 = 3.0;
|
||||
// Taken from https://searchfox.org/mozilla-central/rev/c633ffa4c4611f202ca11270dcddb7b29edddff8/layout/painting/nsCSSRendering.cpp#4412
|
||||
pub const MAX_BLUR_RADIUS : f32 = 300.;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
// A cache key that uniquely identifies a minimally sized
|
||||
// and blurred box-shadow rect that can be stored in the
|
||||
// texture cache and applied to clip-masks.
|
||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct BoxShadowCacheKey {
|
||||
pub width: Au,
|
||||
pub height: Au,
|
||||
pub blur_radius: Au,
|
||||
pub spread_radius: Au,
|
||||
pub offset_x: Au,
|
||||
pub offset_y: Au,
|
||||
pub br_top_left_w: Au,
|
||||
pub br_top_left_h: Au,
|
||||
pub br_top_right_w: Au,
|
||||
pub br_top_right_h: Au,
|
||||
pub br_bottom_left_w: Au,
|
||||
pub br_bottom_left_h: Au,
|
||||
pub br_bottom_right_w: Au,
|
||||
pub br_bottom_right_h: Au,
|
||||
pub blur_radius_dp: i32,
|
||||
pub clip_mode: BoxShadowClipMode,
|
||||
pub rect_size: DeviceIntSize,
|
||||
pub br_top_left: DeviceIntSize,
|
||||
pub br_top_right: DeviceIntSize,
|
||||
pub br_bottom_right: DeviceIntSize,
|
||||
pub br_bottom_left: DeviceIntSize,
|
||||
}
|
||||
|
||||
impl<'a> DisplayListFlattener<'a> {
|
||||
pub fn add_box_shadow(
|
||||
&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
prim_info: &LayerPrimitiveInfo,
|
||||
box_offset: &LayerVector2D,
|
||||
@ -60,33 +77,50 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
let (spread_amount, brush_clip_mode) = match clip_mode {
|
||||
// Inset shadows get smaller as spread radius increases.
|
||||
let (spread_amount, prim_clip_mode) = match clip_mode {
|
||||
BoxShadowClipMode::Outset => {
|
||||
(spread_radius, ClipMode::Clip)
|
||||
(spread_radius, ClipMode::ClipOut)
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
(-spread_radius, ClipMode::ClipOut)
|
||||
(-spread_radius, ClipMode::Clip)
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure the blur radius is somewhat sensible.
|
||||
blur_radius = f32::min(blur_radius, MAX_BLUR_RADIUS);
|
||||
|
||||
// Adjust the border radius of the box shadow per CSS-spec.
|
||||
let shadow_radius = adjust_border_radius_for_box_shadow(
|
||||
border_radius,
|
||||
spread_amount,
|
||||
);
|
||||
|
||||
// Apply parameters that affect where the shadow rect
|
||||
// exists in the local space of the primitive.
|
||||
let shadow_rect = prim_info.rect
|
||||
.translate(box_offset)
|
||||
.inflate(spread_amount, spread_amount);
|
||||
|
||||
// If blur radius is zero, we can use a fast path with
|
||||
// no blur applied.
|
||||
if blur_radius == 0.0 {
|
||||
if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 {
|
||||
// Trivial reject of box-shadows that are not visible.
|
||||
if box_offset.x == 0.0 &&
|
||||
box_offset.y == 0.0 &&
|
||||
spread_amount == 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
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 => {
|
||||
if !shadow_rect.is_well_formed_and_nonempty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(gw): Add a fast path for ClipOut + zero border radius!
|
||||
clips.push(ClipSource::new_rounded_rect(
|
||||
prim_info.rect,
|
||||
@ -107,11 +141,13 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
)
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
clips.push(ClipSource::new_rounded_rect(
|
||||
shadow_rect,
|
||||
shadow_radius,
|
||||
ClipMode::ClipOut
|
||||
));
|
||||
if shadow_rect.is_well_formed_and_nonempty() {
|
||||
clips.push(ClipSource::new_rounded_rect(
|
||||
shadow_rect,
|
||||
shadow_radius,
|
||||
ClipMode::ClipOut
|
||||
));
|
||||
}
|
||||
|
||||
LayerPrimitiveInfo::with_clip(
|
||||
prim_info.rect,
|
||||
@ -140,213 +176,83 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Normal path for box-shadows with a valid blur radius.
|
||||
let blur_offset = BLUR_SAMPLE_SCALE * blur_radius;
|
||||
let mut extra_clips = vec![];
|
||||
|
||||
let cache_key = BoxShadowCacheKey {
|
||||
width: Au::from_f32_px(shadow_rect.size.width),
|
||||
height: Au::from_f32_px(shadow_rect.size.height),
|
||||
blur_radius: Au::from_f32_px(blur_radius),
|
||||
spread_radius: Au::from_f32_px(spread_radius),
|
||||
offset_x: Au::from_f32_px(box_offset.x),
|
||||
offset_y: Au::from_f32_px(box_offset.y),
|
||||
br_top_left_w: Au::from_f32_px(border_radius.top_left.width),
|
||||
br_top_left_h: Au::from_f32_px(border_radius.top_left.height),
|
||||
br_top_right_w: Au::from_f32_px(border_radius.top_right.width),
|
||||
br_top_right_h: Au::from_f32_px(border_radius.top_right.height),
|
||||
br_bottom_left_w: Au::from_f32_px(border_radius.bottom_left.width),
|
||||
br_bottom_left_h: Au::from_f32_px(border_radius.bottom_left.height),
|
||||
br_bottom_right_w: Au::from_f32_px(border_radius.bottom_right.width),
|
||||
br_bottom_right_h: Au::from_f32_px(border_radius.bottom_right.height),
|
||||
// Add a normal clip mask to clip out the contents
|
||||
// of the surrounding primitive.
|
||||
extra_clips.push(ClipSource::new_rounded_rect(
|
||||
prim_info.rect,
|
||||
border_radius,
|
||||
prim_clip_mode,
|
||||
));
|
||||
|
||||
// Get the local rect of where the shadow will be drawn,
|
||||
// expanded to include room for the blurred region.
|
||||
let dest_rect = shadow_rect.inflate(blur_offset, blur_offset);
|
||||
|
||||
// Draw the box-shadow as a solid rect, using a box-shadow
|
||||
// clip mask source.
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::Solid {
|
||||
color: *color,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
// Create the box-shadow clip source.
|
||||
let shadow_clip_source = ClipSource::new_box_shadow(
|
||||
shadow_rect,
|
||||
shadow_radius,
|
||||
dest_rect,
|
||||
blur_radius,
|
||||
clip_mode,
|
||||
};
|
||||
);
|
||||
|
||||
match clip_mode {
|
||||
let prim_info = match clip_mode {
|
||||
BoxShadowClipMode::Outset => {
|
||||
let mut width;
|
||||
let mut height;
|
||||
let brush_prim;
|
||||
let mut image_kind = BrushImageKind::NinePatch;
|
||||
|
||||
// Certain spread-radii make the shadow invalid.
|
||||
if !shadow_rect.is_well_formed_and_nonempty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a minimal size primitive mask to blur. In this
|
||||
// case, we ensure the size of each corner is the same,
|
||||
// to simplify the shader logic that stretches the blurred
|
||||
// result across the primitive.
|
||||
let max_width = shadow_radius.top_left.width
|
||||
.max(shadow_radius.bottom_left.width)
|
||||
.max(shadow_radius.top_right.width)
|
||||
.max(shadow_radius.bottom_right.width);
|
||||
let max_height = shadow_radius.top_left.height
|
||||
.max(shadow_radius.bottom_left.height)
|
||||
.max(shadow_radius.top_right.height)
|
||||
.max(shadow_radius.bottom_right.height);
|
||||
// Add the box-shadow clip source.
|
||||
extra_clips.push(shadow_clip_source);
|
||||
|
||||
width = 2.0 * max_width + BLUR_SAMPLE_SCALE * blur_radius;
|
||||
height = 2.0 * max_height + BLUR_SAMPLE_SCALE * blur_radius;
|
||||
|
||||
// If the width or height ends up being bigger than the original
|
||||
// primitive shadow rect, just blur the entire rect and draw that
|
||||
// as a simple blit.
|
||||
if width > prim_info.rect.size.width || height > prim_info.rect.size.height {
|
||||
image_kind = BrushImageKind::Simple;
|
||||
width = prim_info.rect.size.width + spread_amount * 2.0;
|
||||
height = prim_info.rect.size.height + spread_amount * 2.0;
|
||||
}
|
||||
|
||||
let clip_rect = LayerRect::new(
|
||||
LayerPoint::zero(),
|
||||
LayerSize::new(width, height)
|
||||
);
|
||||
|
||||
brush_prim = BrushPrimitive::new(
|
||||
BrushKind::Mask {
|
||||
clip_mode: brush_clip_mode,
|
||||
rect: clip_rect,
|
||||
radii: shadow_radius,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
// Construct a mask primitive to add to the picture.
|
||||
let brush_rect = LayerRect::new(LayerPoint::zero(),
|
||||
LayerSize::new(width, height));
|
||||
let brush_info = LayerPrimitiveInfo::new(brush_rect);
|
||||
let brush_prim_index = self.create_primitive(
|
||||
&brush_info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(brush_prim),
|
||||
);
|
||||
|
||||
// Create a box shadow picture and add the mask primitive to it.
|
||||
let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
|
||||
let mut pic_prim = PicturePrimitive::new_box_shadow(
|
||||
blur_radius,
|
||||
*color,
|
||||
clip_mode,
|
||||
image_kind,
|
||||
cache_key,
|
||||
pipeline_id,
|
||||
);
|
||||
pic_prim.add_primitive(
|
||||
brush_prim_index,
|
||||
clip_and_scroll
|
||||
);
|
||||
|
||||
extra_clips.push(ClipSource::new_rounded_rect(
|
||||
prim_info.rect,
|
||||
border_radius,
|
||||
ClipMode::ClipOut,
|
||||
));
|
||||
let pic_info = LayerPrimitiveInfo::with_clip_rect(
|
||||
pic_rect,
|
||||
// Outset shadows are expanded by the shadow
|
||||
// region from the original primitive.
|
||||
LayerPrimitiveInfo::with_clip_rect(
|
||||
dest_rect,
|
||||
*prim_info.local_clip.clip_rect()
|
||||
);
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&pic_info,
|
||||
extra_clips,
|
||||
PrimitiveContainer::Picture(pic_prim),
|
||||
);
|
||||
)
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
// TODO(gw): Inset shadows still need an optimization pass.
|
||||
// We draw and blur way more pixels than needed.
|
||||
|
||||
// Draw a picture that covers the area of the primitive rect.
|
||||
let brush_rect = LayerRect::new(
|
||||
LayerPoint::zero(),
|
||||
prim_info.rect.size
|
||||
);
|
||||
|
||||
// Define where the inset box shadow rect is, local
|
||||
// to the brush rect above.
|
||||
let clip_rect = brush_rect.translate(box_offset)
|
||||
.inflate(spread_amount, spread_amount);
|
||||
|
||||
// Ensure there are more than one pixel around the edges, so that there
|
||||
// is non-zero data to blur, in the case of an inset shadow
|
||||
// with zero spread and zero offset.
|
||||
// The size of inflation edge is determined by std deviation because large
|
||||
// std deviation blur would be downscaled first. Thus, we need more thick
|
||||
// edge to prevent edge get blurred after downscled.
|
||||
let mut adjusted_blur_std_deviation = blur_radius * 0.5;
|
||||
let mut inflate_size = 1.0;
|
||||
while adjusted_blur_std_deviation > MAX_BLUR_STD_DEVIATION {
|
||||
adjusted_blur_std_deviation *= 0.5;
|
||||
inflate_size *= 2.0;
|
||||
// If the inner shadow rect contains the prim
|
||||
// rect, no pixels will be shadowed.
|
||||
if border_radius.is_zero() &&
|
||||
shadow_rect.inflate(-blur_radius, -blur_radius).contains_rect(&prim_info.rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
let brush_rect = brush_rect.inflate(inflate_size + box_offset.x.abs(), inflate_size + box_offset.y.abs());
|
||||
let brush_prim = BrushPrimitive::new(
|
||||
BrushKind::Mask {
|
||||
clip_mode: brush_clip_mode,
|
||||
rect: clip_rect,
|
||||
radii: shadow_radius,
|
||||
},
|
||||
None,
|
||||
);
|
||||
let brush_info = LayerPrimitiveInfo::new(brush_rect);
|
||||
let brush_prim_index = self.create_primitive(
|
||||
&brush_info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(brush_prim),
|
||||
);
|
||||
|
||||
// Create a box shadow picture primitive and add
|
||||
// the brush primitive to it.
|
||||
let mut pic_prim = PicturePrimitive::new_box_shadow(
|
||||
blur_radius,
|
||||
*color,
|
||||
BoxShadowClipMode::Inset,
|
||||
// TODO(gw): Make use of optimization for inset.
|
||||
BrushImageKind::NinePatch,
|
||||
cache_key,
|
||||
pipeline_id,
|
||||
);
|
||||
pic_prim.add_primitive(
|
||||
brush_prim_index,
|
||||
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
|
||||
// rect set below.
|
||||
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,
|
||||
clip_rect
|
||||
);
|
||||
|
||||
// Add a normal clip to ensure nothing gets drawn
|
||||
// outside the primitive rect.
|
||||
if !border_radius.is_zero() {
|
||||
extra_clips.push(ClipSource::new_rounded_rect(
|
||||
prim_info.rect,
|
||||
border_radius,
|
||||
ClipMode::Clip,
|
||||
));
|
||||
// Inset shadows are still visible, even if the
|
||||
// inset shadow rect becomes invalid (they will
|
||||
// just look like a solid rectangle).
|
||||
if shadow_rect.is_well_formed_and_nonempty() {
|
||||
extra_clips.push(shadow_clip_source);
|
||||
}
|
||||
|
||||
// Add the picture primitive to the frame.
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&pic_info,
|
||||
extra_clips,
|
||||
PrimitiveContainer::Picture(pic_prim),
|
||||
);
|
||||
// Inset shadows draw inside the original primitive.
|
||||
prim_info.clone()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
extra_clips,
|
||||
PrimitiveContainer::Brush(prim),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,18 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
|
||||
use api::{ImageRendering, LayerRect, LayoutPoint, LayoutVector2D, LocalClip};
|
||||
use api::{ImageRendering, LayerRect, LayerSize, LayoutPoint, LayoutVector2D, LocalClip};
|
||||
use api::{BoxShadowClipMode, LayerPoint, LayerToWorldScale};
|
||||
use border::{BorderCornerClipSource, ensure_no_corner_overlap};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
|
||||
use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId};
|
||||
use ellipse::Ellipse;
|
||||
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
|
||||
use gpu_types::ClipScrollNodeIndex;
|
||||
use prim_store::{ClipData, ImageMaskData};
|
||||
use resource_cache::{ImageRequest, ResourceCache};
|
||||
use render_task::to_cache_size;
|
||||
use resource_cache::{CacheItem, ImageRequest, ResourceCache};
|
||||
use util::{LayerToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
|
||||
use util::extract_inner_rect_safe;
|
||||
use std::sync::Arc;
|
||||
@ -78,6 +81,7 @@ pub enum ClipSource {
|
||||
/// adjacent border edges. Expand to handle dotted style
|
||||
/// and different styles per edge.
|
||||
BorderCorner(BorderCornerClipSource),
|
||||
BoxShadow(BoxShadowClipSource),
|
||||
}
|
||||
|
||||
impl From<ClipRegion> for ClipSources {
|
||||
@ -115,6 +119,89 @@ impl ClipSource {
|
||||
clip_mode,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_box_shadow(
|
||||
shadow_rect: LayerRect,
|
||||
shadow_radius: BorderRadius,
|
||||
prim_shadow_rect: LayerRect,
|
||||
blur_radius: f32,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
) -> ClipSource {
|
||||
// Get the fractional offsets required to match the
|
||||
// source rect with a minimal rect.
|
||||
let fract_offset = LayerPoint::new(
|
||||
shadow_rect.origin.x.fract().abs(),
|
||||
shadow_rect.origin.y.fract().abs(),
|
||||
);
|
||||
let fract_size = LayerSize::new(
|
||||
shadow_rect.size.width.fract().abs(),
|
||||
shadow_rect.size.height.fract().abs(),
|
||||
);
|
||||
|
||||
// Create a minimal size primitive mask to blur. In this
|
||||
// case, we ensure the size of each corner is the same,
|
||||
// to simplify the shader logic that stretches the blurred
|
||||
// result across the primitive.
|
||||
let max_corner_width = shadow_radius.top_left.width
|
||||
.max(shadow_radius.bottom_left.width)
|
||||
.max(shadow_radius.top_right.width)
|
||||
.max(shadow_radius.bottom_right.width);
|
||||
let max_corner_height = shadow_radius.top_left.height
|
||||
.max(shadow_radius.bottom_left.height)
|
||||
.max(shadow_radius.top_right.height)
|
||||
.max(shadow_radius.bottom_right.height);
|
||||
|
||||
// Get maximum distance that can be affected by given blur radius.
|
||||
let blur_region = (BLUR_SAMPLE_SCALE * blur_radius).ceil();
|
||||
|
||||
// If the largest corner is smaller than the blur radius, we need to ensure
|
||||
// that it's big enough that the corners don't affect the middle segments.
|
||||
let used_corner_width = max_corner_width.max(blur_region);
|
||||
let used_corner_height = max_corner_height.max(blur_region);
|
||||
|
||||
// Minimal nine-patch size, corner + internal + corner.
|
||||
let min_shadow_rect_size = LayerSize::new(
|
||||
2.0 * used_corner_width + blur_region,
|
||||
2.0 * used_corner_height + blur_region,
|
||||
);
|
||||
|
||||
// The minimal rect to blur.
|
||||
let mut minimal_shadow_rect = LayerRect::new(
|
||||
LayerPoint::new(
|
||||
blur_region + fract_offset.x,
|
||||
blur_region + fract_offset.y,
|
||||
),
|
||||
LayerSize::new(
|
||||
min_shadow_rect_size.width + fract_size.width,
|
||||
min_shadow_rect_size.height + fract_size.height,
|
||||
),
|
||||
);
|
||||
|
||||
// If the width or height ends up being bigger than the original
|
||||
// primitive shadow rect, just blur the entire rect and draw that
|
||||
// as a simple blit. This is necessary for correctness, since the
|
||||
// blur of one corner may affect the blur in another corner.
|
||||
minimal_shadow_rect.size.width = minimal_shadow_rect.size.width.min(shadow_rect.size.width);
|
||||
minimal_shadow_rect.size.height = minimal_shadow_rect.size.height.min(shadow_rect.size.height);
|
||||
|
||||
// Expand the shadow rect by enough room for the blur to take effect.
|
||||
let shadow_rect_alloc_size = LayerSize::new(
|
||||
2.0 * blur_region + minimal_shadow_rect.size.width.ceil(),
|
||||
2.0 * blur_region + minimal_shadow_rect.size.height.ceil(),
|
||||
);
|
||||
|
||||
ClipSource::BoxShadow(BoxShadowClipSource {
|
||||
shadow_rect_alloc_size,
|
||||
shadow_radius,
|
||||
prim_shadow_rect,
|
||||
blur_radius,
|
||||
clip_mode,
|
||||
cache_item: CacheItem::invalid(),
|
||||
cache_key: None,
|
||||
clip_data_handle: GpuCacheHandle::new(),
|
||||
minimal_shadow_rect,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -186,6 +273,7 @@ impl ClipSources {
|
||||
local_inner = local_inner
|
||||
.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
|
||||
}
|
||||
ClipSource::BoxShadow(..) |
|
||||
ClipSource::BorderCorner { .. } => {
|
||||
can_calculate_inner_rect = false;
|
||||
break;
|
||||
@ -210,6 +298,7 @@ impl ClipSources {
|
||||
&mut self,
|
||||
gpu_cache: &mut GpuCache,
|
||||
resource_cache: &mut ResourceCache,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) {
|
||||
for &mut (ref mut source, ref mut handle) in &mut self.clips {
|
||||
if let Some(mut request) = gpu_cache.request(handle) {
|
||||
@ -218,6 +307,15 @@ impl ClipSources {
|
||||
let data = ImageMaskData { local_rect: mask.rect };
|
||||
data.write_gpu_blocks(request);
|
||||
}
|
||||
ClipSource::BoxShadow(ref info) => {
|
||||
request.push([
|
||||
info.shadow_rect_alloc_size.width,
|
||||
info.shadow_rect_alloc_size.height,
|
||||
info.clip_mode as i32 as f32,
|
||||
0.0,
|
||||
]);
|
||||
request.push(info.prim_shadow_rect);
|
||||
}
|
||||
ClipSource::Rectangle(rect) => {
|
||||
let data = ClipData::uniform(rect, 0.0, ClipMode::Clip);
|
||||
data.write(&mut request);
|
||||
@ -232,15 +330,49 @@ impl ClipSources {
|
||||
}
|
||||
}
|
||||
|
||||
if let ClipSource::Image(ref mask) = *source {
|
||||
resource_cache.request_image(
|
||||
ImageRequest {
|
||||
key: mask.image,
|
||||
rendering: ImageRendering::Auto,
|
||||
tile: None,
|
||||
},
|
||||
gpu_cache,
|
||||
);
|
||||
match *source {
|
||||
ClipSource::Image(ref mask) => {
|
||||
resource_cache.request_image(
|
||||
ImageRequest {
|
||||
key: mask.image,
|
||||
rendering: ImageRendering::Auto,
|
||||
tile: None,
|
||||
},
|
||||
gpu_cache,
|
||||
);
|
||||
}
|
||||
ClipSource::BoxShadow(ref mut info) => {
|
||||
// Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
|
||||
// "the image that would be generated by applying to the shadow a
|
||||
// Gaussian blur with a standard deviation equal to half the blur radius."
|
||||
let blur_radius_dp = (info.blur_radius * 0.5 * device_pixel_scale.0).round();
|
||||
|
||||
// Create the cache key for this box-shadow render task.
|
||||
let content_scale = LayerToWorldScale::new(1.0) * device_pixel_scale;
|
||||
let cache_size = to_cache_size(info.shadow_rect_alloc_size * content_scale);
|
||||
let bs_cache_key = BoxShadowCacheKey {
|
||||
blur_radius_dp: blur_radius_dp as i32,
|
||||
clip_mode: info.clip_mode,
|
||||
rect_size: (info.shadow_rect_alloc_size * content_scale).round().to_i32(),
|
||||
br_top_left: (info.shadow_radius.top_left * content_scale).round().to_i32(),
|
||||
br_top_right: (info.shadow_radius.top_right * content_scale).round().to_i32(),
|
||||
br_bottom_right: (info.shadow_radius.bottom_right * content_scale).round().to_i32(),
|
||||
br_bottom_left: (info.shadow_radius.bottom_left * content_scale).round().to_i32(),
|
||||
};
|
||||
|
||||
info.cache_key = Some((cache_size, bs_cache_key));
|
||||
|
||||
if let Some(mut request) = gpu_cache.request(&mut info.clip_data_handle) {
|
||||
let data = ClipData::rounded_rect(
|
||||
&info.minimal_shadow_rect,
|
||||
&info.shadow_radius,
|
||||
ClipMode::Clip,
|
||||
);
|
||||
|
||||
data.write(&mut request);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +370,11 @@ impl ClipScrollNode {
|
||||
};
|
||||
|
||||
let clip_sources = clip_store.get_mut(clip_sources_handle);
|
||||
clip_sources.update(gpu_cache, resource_cache);
|
||||
clip_sources.update(
|
||||
gpu_cache,
|
||||
resource_cache,
|
||||
device_pixel_scale,
|
||||
);
|
||||
let (screen_inner_rect, screen_outer_rect) =
|
||||
clip_sources.get_screen_bounds(&self.world_viewport_transform, device_pixel_scale);
|
||||
|
||||
|
@ -741,7 +741,6 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
let mut prim_info = prim_info.clone();
|
||||
prim_info.rect = bounds;
|
||||
self.add_box_shadow(
|
||||
pipeline_id,
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
&box_shadow_info.offset,
|
||||
@ -1312,9 +1311,8 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
*composite_mode = Some(PictureCompositeMode::Blit);
|
||||
}
|
||||
}
|
||||
PictureKind::TextShadow { .. } |
|
||||
PictureKind::BoxShadow { .. } => {
|
||||
panic!("bug: text/box pictures invalid here");
|
||||
PictureKind::TextShadow { .. } => {
|
||||
panic!("bug: text pictures invalid here");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use gpu_cache::GpuCache;
|
||||
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
|
||||
use hit_test::{HitTester, HitTestingRun};
|
||||
use internal_types::{FastHashMap};
|
||||
use picture::{ContentOrigin, PictureSurface};
|
||||
use picture::{ContentOrigin};
|
||||
use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveRun, PrimitiveStore};
|
||||
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
|
||||
use render_backend::FrameId;
|
||||
@ -235,7 +235,7 @@ impl FrameBuilder {
|
||||
);
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(root_render_task);
|
||||
pic.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
pic.surface = Some(render_task_id);
|
||||
Some(render_task_id)
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,15 @@ use render_task::RenderTaskAddress;
|
||||
|
||||
// Contains type that must exactly match the same structures declared in GLSL.
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[repr(C)]
|
||||
pub enum RasterizationSpace {
|
||||
Local = 0,
|
||||
Screen = 1,
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
@ -195,16 +204,6 @@ impl From<BrushInstance> for PrimitiveInstance {
|
||||
}
|
||||
}
|
||||
|
||||
// Defines how a brush image is stretched onto the primitive.
|
||||
// In the future, we may draw with segments for each portion
|
||||
// of the primitive, in which case this will be redundant.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum BrushImageKind {
|
||||
Simple = 0, // A normal rect
|
||||
NinePatch = 1, // A nine-patch image (stretch inside segments)
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
@ -244,7 +243,6 @@ pub struct ClipChainRectIndex(pub usize);
|
||||
pub enum PictureType {
|
||||
Image = 1,
|
||||
TextShadow = 2,
|
||||
BoxShadow = 3,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -300,8 +300,10 @@ fn get_regions_for_clip_scroll_node(
|
||||
ClipSource::RoundedRectangle(ref rect, ref radii, ref mode) =>
|
||||
HitTestRegion::RoundedRectangle(*rect, *radii, *mode),
|
||||
ClipSource::Image(ref mask) => HitTestRegion::Rectangle(mask.rect),
|
||||
ClipSource::BorderCorner(_) =>
|
||||
unreachable!("Didn't expect to hit test against BorderCorner"),
|
||||
ClipSource::BorderCorner(_) |
|
||||
ClipSource::BoxShadow(_) => {
|
||||
unreachable!("Didn't expect to hit test against BorderCorner / BoxShadow");
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
@ -2,38 +2,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::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize};
|
||||
use api::{DeviceIntPoint, DeviceIntRect};
|
||||
use api::{LayerPoint, LayerRect, LayerToWorldScale, LayerVector2D};
|
||||
use api::{BoxShadowClipMode, ColorF, FilterOp, MixBlendMode, PipelineId};
|
||||
use api::{ColorF, FilterOp, MixBlendMode, PipelineId};
|
||||
use api::{PremultipliedColorF, Shadow};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
|
||||
use box_shadow::{BLUR_SAMPLE_SCALE};
|
||||
use clip_scroll_tree::ClipScrollNodeIndex;
|
||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState};
|
||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||
use gpu_types::{BrushImageKind, PictureType};
|
||||
use gpu_types::{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;
|
||||
use render_task::{ClearMode, RenderTask};
|
||||
use render_task::{RenderTaskId, RenderTaskLocation, to_cache_size};
|
||||
use scene::{FilterOpHelpers, SceneProperties};
|
||||
use tiling::RenderTargetKind;
|
||||
|
||||
|
||||
// TODO(gw): Rounding the content rect here to device pixels is not
|
||||
// technically correct. Ideally we should ceil() here, and ensure that
|
||||
// the extra part pixel in the case of fractional sizes is correctly
|
||||
// handled. For now, just use rounding which passes the existing
|
||||
// Gecko tests.
|
||||
// Note: zero-square tasks are prohibited in WR task tree, so
|
||||
// we ensure each dimension to be at least the length of 1 after rounding.
|
||||
fn to_cache_size(size: DeviceSize) -> DeviceIntSize {
|
||||
DeviceIntSize::new(
|
||||
1.max(size.width.round() as i32),
|
||||
1.max(size.height.round() as i32),
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
A picture represents a dynamically rendered image. It consists of:
|
||||
|
||||
@ -75,14 +59,6 @@ pub enum PictureKind {
|
||||
blur_radius: f32,
|
||||
content_rect: LayerRect,
|
||||
},
|
||||
BoxShadow {
|
||||
blur_radius: f32,
|
||||
color: ColorF,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
image_kind: BrushImageKind,
|
||||
content_rect: LayerRect,
|
||||
cache_key: BoxShadowCacheKey,
|
||||
},
|
||||
Image {
|
||||
// If a mix-blend-mode, contains the render task for
|
||||
// the readback of the framebuffer that we use to sample
|
||||
@ -112,21 +88,11 @@ pub enum PictureKind {
|
||||
},
|
||||
}
|
||||
|
||||
// The type of surface that a picture can be drawn to.
|
||||
// RenderTask surfaces are not retained across frames.
|
||||
// TextureCache surfaces are stored across frames, and
|
||||
// also shared between display lists.
|
||||
#[derive(Debug)]
|
||||
pub enum PictureSurface {
|
||||
RenderTask(RenderTaskId),
|
||||
TextureCache(CacheItem),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PicturePrimitive {
|
||||
// If this picture is drawn to an intermediate surface,
|
||||
// the associated target information.
|
||||
pub surface: Option<PictureSurface>,
|
||||
pub surface: Option<RenderTaskId>,
|
||||
|
||||
// Details specific to this type of picture.
|
||||
pub kind: PictureKind,
|
||||
@ -193,34 +159,6 @@ impl PicturePrimitive {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_box_shadow(
|
||||
blur_radius: f32,
|
||||
color: ColorF,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
image_kind: BrushImageKind,
|
||||
cache_key: BoxShadowCacheKey,
|
||||
pipeline_id: PipelineId,
|
||||
) -> Self {
|
||||
PicturePrimitive {
|
||||
runs: Vec::new(),
|
||||
surface: None,
|
||||
kind: PictureKind::BoxShadow {
|
||||
blur_radius,
|
||||
color,
|
||||
clip_mode,
|
||||
image_kind,
|
||||
content_rect: LayerRect::zero(),
|
||||
cache_key,
|
||||
},
|
||||
pipeline_id,
|
||||
cull_children: false,
|
||||
brush: BrushPrimitive::new(
|
||||
BrushKind::Picture,
|
||||
None,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_image(
|
||||
composite_mode: Option<PictureCompositeMode>,
|
||||
is_in_3d_context: bool,
|
||||
@ -269,8 +207,8 @@ impl PicturePrimitive {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn update_local_rect(&mut self,
|
||||
prim_local_rect: LayerRect,
|
||||
pub fn update_local_rect(
|
||||
&mut self,
|
||||
prim_run_rect: PrimitiveRunLocalRect,
|
||||
) -> LayerRect {
|
||||
let local_content_rect = prim_run_rect.local_rect_in_actual_parent_space;
|
||||
@ -304,25 +242,6 @@ impl PicturePrimitive {
|
||||
|
||||
content_rect.translate(&offset)
|
||||
}
|
||||
PictureKind::BoxShadow { blur_radius, clip_mode, ref mut content_rect, .. } => {
|
||||
// We need to inflate the content rect if outset.
|
||||
*content_rect = match clip_mode {
|
||||
BoxShadowClipMode::Outset => {
|
||||
let full_offset = blur_radius * BLUR_SAMPLE_SCALE;
|
||||
// For a non-uniform radii, we need to expand
|
||||
// the content rect on all sides for the blur.
|
||||
local_content_rect.inflate(
|
||||
full_offset,
|
||||
full_offset,
|
||||
)
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
local_content_rect
|
||||
}
|
||||
};
|
||||
|
||||
prim_local_rect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,7 +281,7 @@ impl PicturePrimitive {
|
||||
let blur_std_deviation = blur_radius * frame_context.device_pixel_scale.0;
|
||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||
|
||||
let (blur_render_task, _) = RenderTask::new_blur(
|
||||
let blur_render_task = RenderTask::new_blur(
|
||||
blur_std_deviation,
|
||||
picture_task_id,
|
||||
frame_state.render_tasks,
|
||||
@ -373,7 +292,7 @@ impl PicturePrimitive {
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
self.surface = Some(render_task_id);
|
||||
}
|
||||
Some(PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color))) => {
|
||||
let rect = (prim_local_rect.translate(&-offset) * content_scale).round().to_i32();
|
||||
@ -392,7 +311,7 @@ impl PicturePrimitive {
|
||||
let blur_std_deviation = blur_radius * frame_context.device_pixel_scale.0;
|
||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||
|
||||
let (blur_render_task, _) = RenderTask::new_blur(
|
||||
let blur_render_task = RenderTask::new_blur(
|
||||
blur_std_deviation.round(),
|
||||
picture_task_id,
|
||||
frame_state.render_tasks,
|
||||
@ -405,7 +324,7 @@ impl PicturePrimitive {
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
self.surface = Some(render_task_id);
|
||||
}
|
||||
Some(PictureCompositeMode::MixBlend(..)) => {
|
||||
let picture_task = RenderTask::new_picture(
|
||||
@ -426,7 +345,7 @@ impl PicturePrimitive {
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
self.surface = Some(render_task_id);
|
||||
}
|
||||
Some(PictureCompositeMode::Filter(filter)) => {
|
||||
// If this filter is not currently going to affect
|
||||
@ -460,7 +379,7 @@ impl PicturePrimitive {
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
self.surface = Some(render_task_id);
|
||||
}
|
||||
}
|
||||
Some(PictureCompositeMode::Blit) => {
|
||||
@ -477,7 +396,7 @@ impl PicturePrimitive {
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(picture_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
self.surface = Some(render_task_id);
|
||||
}
|
||||
None => {
|
||||
pic_state.tasks.extend(pic_state_for_children.tasks);
|
||||
@ -511,7 +430,7 @@ impl PicturePrimitive {
|
||||
|
||||
let picture_task_id = frame_state.render_tasks.add(picture_task);
|
||||
|
||||
let (blur_render_task, _) = RenderTask::new_blur(
|
||||
let blur_render_task = RenderTask::new_blur(
|
||||
blur_std_deviation,
|
||||
picture_task_id,
|
||||
frame_state.render_tasks,
|
||||
@ -522,78 +441,7 @@ impl PicturePrimitive {
|
||||
|
||||
let render_task_id = frame_state.render_tasks.add(blur_render_task);
|
||||
pic_state.tasks.push(render_task_id);
|
||||
self.surface = Some(PictureSurface::RenderTask(render_task_id));
|
||||
}
|
||||
PictureKind::BoxShadow { blur_radius, clip_mode, color, content_rect, cache_key, .. } => {
|
||||
// TODO(gw): Rounding the content rect here to device pixels is not
|
||||
// technically correct. Ideally we should ceil() here, and ensure that
|
||||
// the extra part pixel in the case of fractional sizes is correctly
|
||||
// handled. For now, just use rounding which passes the existing
|
||||
// Gecko tests.
|
||||
let cache_size = to_cache_size(content_rect.size * content_scale);
|
||||
|
||||
// Request the texture cache item for this box-shadow key. If it
|
||||
// doesn't exist in the cache, the closure is invoked to build
|
||||
// a render task chain to draw the cacheable result.
|
||||
let cache_item = frame_state.resource_cache.request_render_task(
|
||||
RenderTaskCacheKey {
|
||||
size: cache_size,
|
||||
kind: RenderTaskCacheKeyKind::BoxShadow(cache_key),
|
||||
},
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
|render_tasks| {
|
||||
// Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
|
||||
// "the image that would be generated by applying to the shadow a
|
||||
// Gaussian blur with a standard deviation equal to half the blur radius."
|
||||
let device_radius = (blur_radius * frame_context.device_pixel_scale.0).round();
|
||||
let blur_std_deviation = device_radius * 0.5;
|
||||
|
||||
let blur_clear_mode = match clip_mode {
|
||||
BoxShadowClipMode::Outset => {
|
||||
ClearMode::One
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
ClearMode::Zero
|
||||
}
|
||||
};
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
RenderTaskLocation::Dynamic(None, cache_size),
|
||||
prim_index,
|
||||
RenderTargetKind::Alpha,
|
||||
ContentOrigin::Local(content_rect.origin),
|
||||
color.premultiplied(),
|
||||
ClearMode::Zero,
|
||||
Vec::new(),
|
||||
PictureType::BoxShadow,
|
||||
);
|
||||
|
||||
let picture_task_id = render_tasks.add(picture_task);
|
||||
|
||||
let (blur_render_task, scale_factor) = RenderTask::new_blur(
|
||||
blur_std_deviation,
|
||||
picture_task_id,
|
||||
render_tasks,
|
||||
RenderTargetKind::Alpha,
|
||||
blur_clear_mode,
|
||||
color.premultiplied(),
|
||||
);
|
||||
|
||||
let root_task_id = render_tasks.add(blur_render_task);
|
||||
pic_state.tasks.push(root_task_id);
|
||||
|
||||
// TODO(gw): Remove the nastiness with having to pass
|
||||
// the scale factor through the texture cache
|
||||
// item user data. This will disappear once
|
||||
// the brush_picture shader is updated to draw
|
||||
// segments, since the scale factor will not
|
||||
// be used at all then during drawing.
|
||||
(root_task_id, [scale_factor, 0.0, 0.0], false)
|
||||
}
|
||||
);
|
||||
|
||||
self.surface = Some(PictureSurface::TextureCache(cache_item));
|
||||
self.surface = Some(render_task_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -634,9 +482,6 @@ impl PicturePrimitive {
|
||||
}
|
||||
}
|
||||
}
|
||||
PictureKind::BoxShadow { color, .. } => {
|
||||
request.push(color.premultiplied());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipMode, ColorF, ComplexClipRegion};
|
||||
use api::{AlphaType, BorderRadius, BoxShadowClipMode, BuiltDisplayList, 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};
|
||||
@ -190,11 +190,6 @@ pub struct PrimitiveMetadata {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BrushKind {
|
||||
Mask {
|
||||
clip_mode: ClipMode,
|
||||
rect: LayerRect,
|
||||
radii: BorderRadius,
|
||||
},
|
||||
Solid {
|
||||
color: ColorF,
|
||||
},
|
||||
@ -248,7 +243,6 @@ impl BrushKind {
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::LinearGradient { .. } => true,
|
||||
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Clear |
|
||||
BrushKind::Line { .. } => false,
|
||||
}
|
||||
@ -340,27 +334,6 @@ impl BrushPrimitive {
|
||||
// Opaque black with operator dest out
|
||||
request.push(PremultipliedColorF::BLACK);
|
||||
}
|
||||
BrushKind::Mask { clip_mode, rect, radii } => {
|
||||
request.push([
|
||||
clip_mode as u32 as f32,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
]);
|
||||
request.push(rect);
|
||||
request.push([
|
||||
radii.top_left.width,
|
||||
radii.top_left.height,
|
||||
radii.top_right.width,
|
||||
radii.top_right.height,
|
||||
]);
|
||||
request.push([
|
||||
radii.bottom_right.width,
|
||||
radii.bottom_right.height,
|
||||
radii.bottom_left.width,
|
||||
radii.bottom_left.height,
|
||||
]);
|
||||
}
|
||||
BrushKind::Line { color, wavy_line_thickness, style, orientation } => {
|
||||
request.push(color);
|
||||
request.push([
|
||||
@ -990,7 +963,6 @@ impl PrimitiveStore {
|
||||
let opacity = match brush.kind {
|
||||
BrushKind::Clear => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Solid { ref color } => PrimitiveOpacity::from_alpha(color.a),
|
||||
BrushKind::Mask { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Line { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::Image { .. } => PrimitiveOpacity::translucent(),
|
||||
BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(),
|
||||
@ -1206,7 +1178,7 @@ impl PrimitiveStore {
|
||||
|
||||
// Pass the image opacity, so that the cached render task
|
||||
// item inherits the same opacity properties.
|
||||
(target_to_cache_task_id, [0.0; 3], image_properties.descriptor.is_opaque)
|
||||
(target_to_cache_task_id, image_properties.descriptor.is_opaque)
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -1288,7 +1260,6 @@ impl PrimitiveStore {
|
||||
);
|
||||
}
|
||||
}
|
||||
BrushKind::Mask { .. } |
|
||||
BrushKind::Solid { .. } |
|
||||
BrushKind::Clear |
|
||||
BrushKind::Line { .. } |
|
||||
@ -1410,6 +1381,31 @@ impl PrimitiveStore {
|
||||
ClipSource::Rectangle(rect) => {
|
||||
(rect, None, ClipMode::Clip)
|
||||
}
|
||||
ClipSource::BoxShadow(ref info) => {
|
||||
// For inset box shadows, we can clip out any
|
||||
// pixels that are inside the shadow region
|
||||
// and are beyond the inner rect, as they can't
|
||||
// be affected by the blur radius.
|
||||
let inner_clip_mode = match info.clip_mode {
|
||||
BoxShadowClipMode::Outset => None,
|
||||
BoxShadowClipMode::Inset => Some(ClipMode::ClipOut),
|
||||
};
|
||||
|
||||
// Push a region into the segment builder where the
|
||||
// box-shadow can have an effect on the result. This
|
||||
// ensures clip-mask tasks get allocated for these
|
||||
// pixel regions, even if no other clips affect them.
|
||||
segment_builder.push_mask_region(
|
||||
info.prim_shadow_rect,
|
||||
info.prim_shadow_rect.inflate(
|
||||
-0.5 * info.shadow_rect_alloc_size.width,
|
||||
-0.5 * info.shadow_rect_alloc_size.height,
|
||||
),
|
||||
inner_clip_mode,
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
ClipSource::BorderCorner(..) |
|
||||
ClipSource::Image(..) => {
|
||||
// TODO(gw): We can easily extend the segment builder
|
||||
@ -1439,7 +1435,7 @@ impl PrimitiveStore {
|
||||
relative_transform.transform_rect(&local_clip_rect)
|
||||
};
|
||||
|
||||
segment_builder.push_rect(local_clip_rect, radius, mode);
|
||||
segment_builder.push_clip_rect(local_clip_rect, radius, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1531,6 +1527,10 @@ impl PrimitiveStore {
|
||||
bounds,
|
||||
clips.clone(),
|
||||
prim_run_context.scroll_node.coordinate_system_id,
|
||||
frame_state.clip_store,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
frame_state.render_tasks,
|
||||
);
|
||||
|
||||
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
||||
@ -1575,6 +1575,7 @@ impl PrimitiveStore {
|
||||
prim_clips.update(
|
||||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
frame_context.device_pixel_scale,
|
||||
);
|
||||
let (screen_inner_rect, screen_outer_rect) =
|
||||
prim_clips.get_screen_bounds(transform, frame_context.device_pixel_scale);
|
||||
@ -1663,6 +1664,10 @@ impl PrimitiveStore {
|
||||
combined_outer_rect,
|
||||
clips,
|
||||
prim_coordinate_system_id,
|
||||
frame_state.clip_store,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
frame_state.render_tasks,
|
||||
);
|
||||
|
||||
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
||||
@ -1716,7 +1721,6 @@ impl PrimitiveStore {
|
||||
may_need_clip_mask = composite_mode.is_some();
|
||||
(true, Some(reference_frame_index))
|
||||
}
|
||||
PictureKind::BoxShadow { .. } |
|
||||
PictureKind::TextShadow { .. } => {
|
||||
(false, None)
|
||||
}
|
||||
@ -1756,10 +1760,7 @@ impl PrimitiveStore {
|
||||
pic.runs = pic_context_for_children.prim_runs;
|
||||
|
||||
let metadata = &mut self.cpu_metadata[prim_index.0];
|
||||
metadata.local_rect = pic.update_local_rect(
|
||||
metadata.local_rect,
|
||||
result,
|
||||
);
|
||||
metadata.local_rect = pic.update_local_rect(result);
|
||||
}
|
||||
|
||||
let (local_rect, unclipped_device_rect) = {
|
||||
|
@ -3,19 +3,19 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, ImageDescriptor, ImageFormat};
|
||||
use api::PremultipliedColorF;
|
||||
use box_shadow::BoxShadowCacheKey;
|
||||
use clip::ClipWorkItem;
|
||||
use api::{DeviceSize, PremultipliedColorF};
|
||||
use box_shadow::{BoxShadowCacheKey};
|
||||
use clip::{ClipSource, ClipStore, ClipWorkItem};
|
||||
use clip_scroll_tree::CoordinateSystemId;
|
||||
use device::TextureFilter;
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle};
|
||||
use gpu_types::{ImageSource, PictureType};
|
||||
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
|
||||
use gpu_types::{ImageSource, PictureType, RasterizationSpace};
|
||||
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 resource_cache::{CacheItem, ResourceCache};
|
||||
use std::{cmp, ops, usize, f32, i32};
|
||||
use texture_cache::{TextureCache, TextureCacheHandle};
|
||||
use tiling::{RenderPass, RenderTargetIndex};
|
||||
@ -154,6 +154,13 @@ pub struct CacheMaskTask {
|
||||
pub coordinate_system_id: CoordinateSystemId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ClipRegionTask {
|
||||
pub clip_data_address: GpuCacheAddress,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
@ -173,7 +180,6 @@ pub struct BlurTask {
|
||||
pub blur_std_deviation: f32,
|
||||
pub target_kind: RenderTargetKind,
|
||||
pub color: PremultipliedColorF,
|
||||
pub scale_factor: f32,
|
||||
pub uv_rect_handle: GpuCacheHandle,
|
||||
}
|
||||
|
||||
@ -182,7 +188,6 @@ impl BlurTask {
|
||||
fn print_with<T: PrintTreePrinter>(&self, pt: &mut T) {
|
||||
pt.add_item(format!("std deviation: {}", self.blur_std_deviation));
|
||||
pt.add_item(format!("target: {:?}", self.target_kind));
|
||||
pt.add_item(format!("scale: {}", self.scale_factor));
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,6 +224,7 @@ pub struct RenderTaskData {
|
||||
pub enum RenderTaskKind {
|
||||
Picture(PictureTask),
|
||||
CacheMask(CacheMaskTask),
|
||||
ClipRegion(ClipRegionTask),
|
||||
VerticalBlur(BlurTask),
|
||||
HorizontalBlur(BlurTask),
|
||||
Readback(DeviceIntRect),
|
||||
@ -316,9 +322,79 @@ impl RenderTask {
|
||||
outer_rect: DeviceIntRect,
|
||||
clips: Vec<ClipWorkItem>,
|
||||
prim_coordinate_system_id: CoordinateSystemId,
|
||||
clip_store: &mut ClipStore,
|
||||
gpu_cache: &mut GpuCache,
|
||||
resource_cache: &mut ResourceCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
) -> Self {
|
||||
let mut children = Vec::new();
|
||||
|
||||
// Step through the clip sources that make up this mask. If we find
|
||||
// any box-shadow clip sources, request that image from the render
|
||||
// task cache. This allows the blurred box-shadow rect to be cached
|
||||
// in the texture cache across frames.
|
||||
// TODO(gw): Consider moving this logic outside this function, especially
|
||||
// as we add more clip sources that depend on render tasks.
|
||||
// TODO(gw): If this ever shows up in a profile, we could pre-calculate
|
||||
// whether a ClipSources contains any box-shadows and skip
|
||||
// this iteration for the majority of cases.
|
||||
for clip_item in &clips {
|
||||
let clip_sources = clip_store.get_opt_mut(&clip_item.clip_sources).expect("bug");
|
||||
for &mut (ref mut clip, _) in &mut clip_sources.clips {
|
||||
match *clip {
|
||||
ClipSource::BoxShadow(ref mut info) => {
|
||||
let (cache_size, cache_key) = info.cache_key
|
||||
.as_ref()
|
||||
.expect("bug: no cache key set")
|
||||
.clone();
|
||||
let blur_radius_dp = cache_key.blur_radius_dp as f32;
|
||||
let clip_data_address = gpu_cache.get_address(&info.clip_data_handle);
|
||||
|
||||
// Request a cacheable render task with a blurred, minimal
|
||||
// sized box-shadow rect.
|
||||
info.cache_item = resource_cache.request_render_task(
|
||||
RenderTaskCacheKey {
|
||||
size: cache_size,
|
||||
kind: RenderTaskCacheKeyKind::BoxShadow(cache_key),
|
||||
},
|
||||
gpu_cache,
|
||||
render_tasks,
|
||||
|render_tasks| {
|
||||
// Draw the rounded rect.
|
||||
let mask_task = RenderTask::new_rounded_rect_mask(
|
||||
cache_size,
|
||||
clip_data_address,
|
||||
);
|
||||
|
||||
let mask_task_id = render_tasks.add(mask_task);
|
||||
|
||||
// Blur it
|
||||
let blur_render_task = RenderTask::new_blur(
|
||||
blur_radius_dp,
|
||||
mask_task_id,
|
||||
render_tasks,
|
||||
RenderTargetKind::Alpha,
|
||||
ClearMode::Zero,
|
||||
PremultipliedColorF::TRANSPARENT,
|
||||
);
|
||||
|
||||
let root_task_id = render_tasks.add(blur_render_task);
|
||||
children.push(root_task_id);
|
||||
|
||||
(root_task_id, false)
|
||||
}
|
||||
);
|
||||
}
|
||||
ClipSource::Rectangle(..) |
|
||||
ClipSource::RoundedRectangle(..) |
|
||||
ClipSource::Image(..) |
|
||||
ClipSource::BorderCorner(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderTask {
|
||||
children: Vec::new(),
|
||||
children,
|
||||
location: RenderTaskLocation::Dynamic(None, outer_rect.size),
|
||||
kind: RenderTaskKind::CacheMask(CacheMaskTask {
|
||||
actual_rect: outer_rect,
|
||||
@ -330,6 +406,21 @@ impl RenderTask {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_rounded_rect_mask(
|
||||
size: DeviceIntSize,
|
||||
clip_data_address: GpuCacheAddress,
|
||||
) -> Self {
|
||||
RenderTask {
|
||||
children: Vec::new(),
|
||||
location: RenderTaskLocation::Dynamic(None, size),
|
||||
kind: RenderTaskKind::ClipRegion(ClipRegionTask {
|
||||
clip_data_address,
|
||||
}),
|
||||
clear_mode: ClearMode::One,
|
||||
saved_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a render task to apply a blur to a primitive.
|
||||
// The render task chain that is constructed looks like:
|
||||
//
|
||||
@ -355,7 +446,7 @@ impl RenderTask {
|
||||
target_kind: RenderTargetKind,
|
||||
clear_mode: ClearMode,
|
||||
color: PremultipliedColorF,
|
||||
) -> (Self, f32) {
|
||||
) -> Self {
|
||||
// Adjust large std deviation value.
|
||||
let mut adjusted_blur_std_deviation = blur_std_deviation;
|
||||
let blur_target_size = render_tasks[src_task_id].get_dynamic_size();
|
||||
@ -377,7 +468,6 @@ impl RenderTask {
|
||||
);
|
||||
downscaling_src_task_id = render_tasks.add(downscaling_task);
|
||||
}
|
||||
scale_factor = blur_target_size.width as f32 / adjusted_blur_target_size.width as f32;
|
||||
|
||||
let blur_task_v = RenderTask {
|
||||
children: vec![downscaling_src_task_id],
|
||||
@ -386,7 +476,6 @@ impl RenderTask {
|
||||
blur_std_deviation: adjusted_blur_std_deviation,
|
||||
target_kind,
|
||||
color,
|
||||
scale_factor,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
}),
|
||||
clear_mode,
|
||||
@ -402,14 +491,13 @@ impl RenderTask {
|
||||
blur_std_deviation: adjusted_blur_std_deviation,
|
||||
target_kind,
|
||||
color,
|
||||
scale_factor,
|
||||
uv_rect_handle: GpuCacheHandle::new(),
|
||||
}),
|
||||
clear_mode,
|
||||
saved_index: None,
|
||||
};
|
||||
|
||||
(blur_task_h, scale_factor)
|
||||
blur_task_h
|
||||
}
|
||||
|
||||
pub fn new_scaling(
|
||||
@ -466,7 +554,17 @@ impl RenderTask {
|
||||
[
|
||||
task.actual_rect.origin.x as f32,
|
||||
task.actual_rect.origin.y as f32,
|
||||
RasterizationSpace::Screen as i32 as f32,
|
||||
],
|
||||
[0.0; 4],
|
||||
)
|
||||
}
|
||||
RenderTaskKind::ClipRegion(..) => {
|
||||
(
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
RasterizationSpace::Local as i32 as f32,
|
||||
],
|
||||
[0.0; 4],
|
||||
)
|
||||
@ -476,7 +574,7 @@ impl RenderTask {
|
||||
(
|
||||
[
|
||||
task.blur_std_deviation,
|
||||
task.scale_factor,
|
||||
0.0,
|
||||
0.0,
|
||||
],
|
||||
task.color.to_array()
|
||||
@ -521,6 +619,7 @@ impl RenderTask {
|
||||
RenderTaskKind::HorizontalBlur(ref info) => {
|
||||
&info.uv_rect_handle
|
||||
}
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
@ -573,6 +672,7 @@ impl RenderTask {
|
||||
match self.kind {
|
||||
RenderTaskKind::Readback(..) => RenderTargetKind::Color,
|
||||
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::CacheMask(..) => {
|
||||
RenderTargetKind::Alpha
|
||||
}
|
||||
@ -609,8 +709,15 @@ impl RenderTask {
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::HorizontalBlur(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::Blit(..) => false,
|
||||
RenderTaskKind::CacheMask(..) => true,
|
||||
|
||||
// TODO(gw): For now, we've disabled the shared clip mask
|
||||
// optimization. It's of dubious value in the
|
||||
// future once we start to cache clip tasks anyway.
|
||||
// I have left shared texture support here though,
|
||||
// just in case we want it in the future.
|
||||
RenderTaskKind::CacheMask(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -631,6 +738,7 @@ impl RenderTask {
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) |
|
||||
RenderTaskKind::Blit(..) |
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::CacheMask(..) => {
|
||||
return;
|
||||
}
|
||||
@ -659,6 +767,9 @@ impl RenderTask {
|
||||
pt.new_level(format!("CacheMask with {} clips", task.clips.len()));
|
||||
pt.add_item(format!("rect: {:?}", task.actual_rect));
|
||||
}
|
||||
RenderTaskKind::ClipRegion(..) => {
|
||||
pt.new_level("ClipRegion".to_owned());
|
||||
}
|
||||
RenderTaskKind::VerticalBlur(ref task) => {
|
||||
pt.new_level("VerticalBlur".to_owned());
|
||||
task.print_with(pt);
|
||||
@ -777,7 +888,7 @@ impl RenderTaskCache {
|
||||
gpu_cache: &mut GpuCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
mut f: F,
|
||||
) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, [f32; 3], bool) {
|
||||
) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, bool) {
|
||||
// Get the texture cache handle for this cache key,
|
||||
// or create one.
|
||||
let cache_entry = self.entries
|
||||
@ -790,7 +901,7 @@ impl RenderTaskCache {
|
||||
if texture_cache.request(&mut cache_entry.handle, gpu_cache) {
|
||||
// Invoke user closure to get render task chain
|
||||
// to draw this into the texture cache.
|
||||
let (render_task_id, user_data, is_opaque) = f(render_tasks);
|
||||
let (render_task_id, is_opaque) = f(render_tasks);
|
||||
let render_task = &mut render_tasks[render_task_id];
|
||||
|
||||
// Select the right texture page to allocate from.
|
||||
@ -825,7 +936,7 @@ impl RenderTaskCache {
|
||||
descriptor,
|
||||
TextureFilter::Linear,
|
||||
None,
|
||||
user_data,
|
||||
[0.0; 3],
|
||||
None,
|
||||
gpu_cache,
|
||||
);
|
||||
@ -849,3 +960,17 @@ impl RenderTaskCache {
|
||||
texture_cache.get(&cache_entry.handle)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gw): Rounding the content rect here to device pixels is not
|
||||
// technically correct. Ideally we should ceil() here, and ensure that
|
||||
// the extra part pixel in the case of fractional sizes is correctly
|
||||
// handled. For now, just use rounding which passes the existing
|
||||
// Gecko tests.
|
||||
// Note: zero-square tasks are prohibited in WR task tree, so
|
||||
// we ensure each dimension to be at least the length of 1 after rounding.
|
||||
pub fn to_cache_size(size: DeviceSize) -> DeviceIntSize {
|
||||
DeviceIntSize::new(
|
||||
1.max(size.width.round() as i32),
|
||||
1.max(size.height.round() as i32),
|
||||
)
|
||||
}
|
||||
|
@ -113,14 +113,6 @@ const GPU_TAG_BRUSH_SOLID: GpuProfileTag = GpuProfileTag {
|
||||
label: "B_Solid",
|
||||
color: debug_colors::RED,
|
||||
};
|
||||
const GPU_TAG_BRUSH_MASK: GpuProfileTag = GpuProfileTag {
|
||||
label: "B_Mask",
|
||||
color: debug_colors::BLACK,
|
||||
};
|
||||
const GPU_TAG_BRUSH_PICTURE: GpuProfileTag = GpuProfileTag {
|
||||
label: "B_Picture",
|
||||
color: debug_colors::SILVER,
|
||||
};
|
||||
const GPU_TAG_BRUSH_LINE: GpuProfileTag = GpuProfileTag {
|
||||
label: "Line",
|
||||
color: debug_colors::DARKRED,
|
||||
@ -221,7 +213,6 @@ impl BatchKind {
|
||||
BatchKind::SplitComposite => "SplitComposite",
|
||||
BatchKind::Brush(kind) => {
|
||||
match kind {
|
||||
BrushBatchKind::Picture => "Brush (Picture)",
|
||||
BrushBatchKind::Solid => "Brush (Solid)",
|
||||
BrushBatchKind::Line => "Brush (Line)",
|
||||
BrushBatchKind::Image(..) => "Brush (Image)",
|
||||
@ -242,7 +233,6 @@ impl BatchKind {
|
||||
BatchKind::SplitComposite => GPU_TAG_PRIM_SPLIT_COMPOSITE,
|
||||
BatchKind::Brush(kind) => {
|
||||
match kind {
|
||||
BrushBatchKind::Picture => GPU_TAG_BRUSH_PICTURE,
|
||||
BrushBatchKind::Solid => GPU_TAG_BRUSH_SOLID,
|
||||
BrushBatchKind::Line => GPU_TAG_BRUSH_LINE,
|
||||
BrushBatchKind::Image(..) => GPU_TAG_BRUSH_IMAGE,
|
||||
@ -1602,8 +1592,6 @@ pub struct Renderer {
|
||||
cs_blur_rgba8: LazilyCompiledShader,
|
||||
|
||||
// Brush shaders
|
||||
brush_mask_rounded_rect: LazilyCompiledShader,
|
||||
brush_picture: BrushShader,
|
||||
brush_solid: BrushShader,
|
||||
brush_line: BrushShader,
|
||||
brush_image: Vec<Option<BrushShader>>,
|
||||
@ -1617,6 +1605,7 @@ pub struct Renderer {
|
||||
/// draw clip instances into the cached clip mask. The results
|
||||
/// of these shaders are also used by the primitive shaders.
|
||||
cs_clip_rectangle: LazilyCompiledShader,
|
||||
cs_clip_box_shadow: LazilyCompiledShader,
|
||||
cs_clip_image: LazilyCompiledShader,
|
||||
cs_clip_border: LazilyCompiledShader,
|
||||
|
||||
@ -1801,14 +1790,6 @@ impl Renderer {
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let brush_mask_rounded_rect = try!{
|
||||
LazilyCompiledShader::new(ShaderKind::Brush,
|
||||
"brush_mask_rounded_rect",
|
||||
&[],
|
||||
&mut device,
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let brush_solid = try!{
|
||||
BrushShader::new("brush_solid",
|
||||
&mut device,
|
||||
@ -1837,13 +1818,6 @@ impl Renderer {
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let brush_picture = try!{
|
||||
BrushShader::new("brush_picture",
|
||||
&mut device,
|
||||
&[],
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let brush_radial_gradient = try!{
|
||||
BrushShader::new("brush_radial_gradient",
|
||||
&mut device,
|
||||
@ -1890,6 +1864,14 @@ impl Renderer {
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let cs_clip_box_shadow = try!{
|
||||
LazilyCompiledShader::new(ShaderKind::ClipCache,
|
||||
"cs_clip_box_shadow",
|
||||
&[],
|
||||
&mut device,
|
||||
options.precache_shaders)
|
||||
};
|
||||
|
||||
let cs_clip_image = try!{
|
||||
LazilyCompiledShader::new(ShaderKind::ClipCache,
|
||||
"cs_clip_image",
|
||||
@ -2272,8 +2254,6 @@ impl Renderer {
|
||||
cs_text_run,
|
||||
cs_blur_a8,
|
||||
cs_blur_rgba8,
|
||||
brush_mask_rounded_rect,
|
||||
brush_picture,
|
||||
brush_solid,
|
||||
brush_line,
|
||||
brush_image,
|
||||
@ -2283,6 +2263,7 @@ impl Renderer {
|
||||
brush_radial_gradient,
|
||||
brush_linear_gradient,
|
||||
cs_clip_rectangle,
|
||||
cs_clip_box_shadow,
|
||||
cs_clip_border,
|
||||
cs_clip_image,
|
||||
ps_text_run,
|
||||
@ -2514,6 +2495,11 @@ impl Renderer {
|
||||
"Borders",
|
||||
target.clip_batcher.borders.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Clip,
|
||||
"BoxShadows",
|
||||
target.clip_batcher.box_shadows.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Cache,
|
||||
"Vertical Blur",
|
||||
@ -2529,11 +2515,6 @@ impl Renderer {
|
||||
"Rectangles",
|
||||
target.clip_batcher.rectangles.len(),
|
||||
);
|
||||
debug_target.add(
|
||||
debug_server::BatchKind::Cache,
|
||||
"Rectangle Brush (Rounded Rect)",
|
||||
target.brush_mask_rounded_rects.len(),
|
||||
);
|
||||
for (_, items) in target.clip_batcher.images.iter() {
|
||||
debug_target.add(debug_server::BatchKind::Clip, "Image mask", items.len());
|
||||
}
|
||||
@ -3202,15 +3183,6 @@ impl Renderer {
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
BrushBatchKind::Picture => {
|
||||
self.brush_picture.bind(
|
||||
&mut self.device,
|
||||
key.blend_mode,
|
||||
projection,
|
||||
0,
|
||||
&mut self.renderer_errors,
|
||||
);
|
||||
}
|
||||
BrushBatchKind::Line => {
|
||||
self.brush_line.bind(
|
||||
&mut self.device,
|
||||
@ -3977,20 +3949,6 @@ impl Renderer {
|
||||
|
||||
self.handle_scaling(render_tasks, &target.scalings, SourceTexture::CacheA8);
|
||||
|
||||
if !target.brush_mask_rounded_rects.is_empty() {
|
||||
self.device.set_blend(false);
|
||||
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_BRUSH_MASK);
|
||||
self.brush_mask_rounded_rect
|
||||
.bind(&mut self.device, projection, 0, &mut self.renderer_errors);
|
||||
self.draw_instanced_batch(
|
||||
&target.brush_mask_rounded_rects,
|
||||
VertexArrayKind::Primitive,
|
||||
&BatchTextures::no_texture(),
|
||||
stats,
|
||||
);
|
||||
}
|
||||
|
||||
// Draw the clip items into the tiled alpha mask.
|
||||
{
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_CACHE_CLIP);
|
||||
@ -4050,6 +4008,26 @@ impl Renderer {
|
||||
stats,
|
||||
);
|
||||
}
|
||||
// draw box-shadow clips
|
||||
for (mask_texture_id, items) in target.clip_batcher.box_shadows.iter() {
|
||||
let _gm2 = self.gpu_profile.start_marker("box-shadows");
|
||||
let textures = BatchTextures {
|
||||
colors: [
|
||||
mask_texture_id.clone(),
|
||||
SourceTexture::Invalid,
|
||||
SourceTexture::Invalid,
|
||||
],
|
||||
};
|
||||
self.cs_clip_box_shadow
|
||||
.bind(&mut self.device, projection, 0, &mut self.renderer_errors);
|
||||
self.draw_instanced_batch(
|
||||
items,
|
||||
VertexArrayKind::Clip,
|
||||
&textures,
|
||||
stats,
|
||||
);
|
||||
}
|
||||
|
||||
// draw image masks
|
||||
for (mask_texture_id, items) in target.clip_batcher.images.iter() {
|
||||
let _gm2 = self.gpu_profile.start_marker("clip images");
|
||||
@ -4683,8 +4661,6 @@ impl Renderer {
|
||||
self.cs_text_run.deinit(&mut self.device);
|
||||
self.cs_blur_a8.deinit(&mut self.device);
|
||||
self.cs_blur_rgba8.deinit(&mut self.device);
|
||||
self.brush_mask_rounded_rect.deinit(&mut self.device);
|
||||
self.brush_picture.deinit(&mut self.device);
|
||||
self.brush_solid.deinit(&mut self.device);
|
||||
self.brush_line.deinit(&mut self.device);
|
||||
self.brush_blend.deinit(&mut self.device);
|
||||
@ -4692,6 +4668,7 @@ impl Renderer {
|
||||
self.brush_radial_gradient.deinit(&mut self.device);
|
||||
self.brush_linear_gradient.deinit(&mut self.device);
|
||||
self.cs_clip_rectangle.deinit(&mut self.device);
|
||||
self.cs_clip_box_shadow.deinit(&mut self.device);
|
||||
self.cs_clip_image.deinit(&mut self.device);
|
||||
self.cs_clip_border.deinit(&mut self.device);
|
||||
self.ps_text_run.deinit(&mut self.device);
|
||||
|
@ -320,7 +320,7 @@ impl ResourceCache {
|
||||
gpu_cache: &mut GpuCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
f: F,
|
||||
) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, [f32; 3], bool) {
|
||||
) -> CacheItem where F: FnMut(&mut RenderTaskTree) -> (RenderTaskId, bool) {
|
||||
self.cached_render_tasks.request_render_task(
|
||||
key,
|
||||
&mut self.texture_cache,
|
||||
|
@ -144,14 +144,14 @@ impl Event {
|
||||
#[derive(Debug)]
|
||||
struct Item {
|
||||
rect: LayerRect,
|
||||
mode: ClipMode,
|
||||
mode: Option<ClipMode>,
|
||||
flags: ItemFlags,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
fn new(
|
||||
rect: LayerRect,
|
||||
mode: ClipMode,
|
||||
mode: Option<ClipMode>,
|
||||
has_mask: bool,
|
||||
) -> Item {
|
||||
let flags = if has_mask {
|
||||
@ -192,15 +192,86 @@ impl SegmentBuilder {
|
||||
inner_rect,
|
||||
};
|
||||
|
||||
builder.push_rect(local_rect, None, ClipMode::Clip);
|
||||
builder.push_rect(local_clip_rect, None, ClipMode::Clip);
|
||||
builder.push_clip_rect(local_rect, None, ClipMode::Clip);
|
||||
builder.push_clip_rect(local_clip_rect, None, ClipMode::Clip);
|
||||
|
||||
builder
|
||||
}
|
||||
|
||||
// Push a region defined by an inner and outer rect where there
|
||||
// is a mask required. This ensures that segments which intersect
|
||||
// with these areas will get a clip mask task allocated. This
|
||||
// is currently used to mark where a box-shadow region can affect
|
||||
// the pixels of a clip-mask. It might be useful for other types
|
||||
// such as dashed and dotted borders in the future.
|
||||
pub fn push_mask_region(
|
||||
&mut self,
|
||||
outer_rect: LayerRect,
|
||||
inner_rect: LayerRect,
|
||||
inner_clip_mode: Option<ClipMode>,
|
||||
) {
|
||||
debug_assert!(outer_rect.contains_rect(&inner_rect));
|
||||
|
||||
let p0 = outer_rect.origin;
|
||||
let p1 = inner_rect.origin;
|
||||
let p2 = inner_rect.bottom_right();
|
||||
let p3 = outer_rect.bottom_right();
|
||||
|
||||
let segments = &[
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p0.x, p0.y),
|
||||
LayerSize::new(p1.x - p0.x, p1.y - p0.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p2.x, p0.y),
|
||||
LayerSize::new(p3.x - p2.x, p1.y - p0.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p2.x, p2.y),
|
||||
LayerSize::new(p3.x - p2.x, p3.y - p2.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p0.x, p2.y),
|
||||
LayerSize::new(p1.x - p0.x, p3.y - p2.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p1.x, p0.y),
|
||||
LayerSize::new(p2.x - p1.x, p1.y - p0.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p2.x, p1.y),
|
||||
LayerSize::new(p3.x - p2.x, p2.y - p1.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p1.x, p2.y),
|
||||
LayerSize::new(p2.x - p1.x, p3.y - p2.y),
|
||||
),
|
||||
LayerRect::new(
|
||||
LayerPoint::new(p0.x, p1.y),
|
||||
LayerSize::new(p1.x - p0.x, p2.y - p1.y),
|
||||
),
|
||||
];
|
||||
|
||||
for segment in segments {
|
||||
self.items.push(Item::new(
|
||||
*segment,
|
||||
None,
|
||||
true
|
||||
));
|
||||
}
|
||||
|
||||
if inner_clip_mode.is_some() {
|
||||
self.items.push(Item::new(
|
||||
inner_rect,
|
||||
inner_clip_mode,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Push some kind of clipping region into the segment builder.
|
||||
// If radius is None, it's a simple rect.
|
||||
pub fn push_rect(
|
||||
pub fn push_clip_rect(
|
||||
&mut self,
|
||||
rect: LayerRect,
|
||||
radius: Option<BorderRadius>,
|
||||
@ -213,6 +284,7 @@ impl SegmentBuilder {
|
||||
bounding_rect.intersection(&rect)
|
||||
});
|
||||
}
|
||||
let mode = Some(mode);
|
||||
|
||||
match radius {
|
||||
Some(radius) => {
|
||||
@ -480,7 +552,7 @@ fn emit_segment_if_needed(
|
||||
if item.flags.contains(ItemFlags::X_ACTIVE | ItemFlags::Y_ACTIVE) {
|
||||
has_clip_mask |= item.flags.contains(ItemFlags::HAS_MASK);
|
||||
|
||||
if item.mode == ClipMode::ClipOut && !item.flags.contains(ItemFlags::HAS_MASK) {
|
||||
if item.mode == Some(ClipMode::ClipOut) && !item.flags.contains(ItemFlags::HAS_MASK) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
@ -578,7 +650,7 @@ mod test {
|
||||
);
|
||||
let mut segments = Vec::new();
|
||||
for &(rect, radius, mode) in clips {
|
||||
sb.push_rect(rect, radius, mode);
|
||||
sb.push_clip_rect(rect, radius, mode);
|
||||
}
|
||||
sb.build(|segment| {
|
||||
segments.push(Segment {
|
||||
|
@ -10,15 +10,14 @@ use clip::{ClipStore};
|
||||
use clip_scroll_tree::{ClipScrollTree, ClipScrollNodeIndex};
|
||||
use device::{FrameId, Texture};
|
||||
use gpu_cache::{GpuCache};
|
||||
use gpu_types::{BlurDirection, BlurInstance, BrushFlags, BrushInstance, ClipChainRectIndex};
|
||||
use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex as GPUClipScrollNodeIndex};
|
||||
use gpu_types::{PrimitiveInstance};
|
||||
use gpu_types::{BlurDirection, BlurInstance};
|
||||
use gpu_types::{ClipScrollNodeData};
|
||||
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
|
||||
use picture::{PictureKind};
|
||||
use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveKind, PrimitiveStore};
|
||||
use prim_store::{BrushKind, DeferredResolve, EdgeAaSegmentMask};
|
||||
use prim_store::{DeferredResolve};
|
||||
use profiler::FrameProfileCounters;
|
||||
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
|
||||
use render_task::{BlitSource, RenderTaskId, RenderTaskKind};
|
||||
use render_task::{BlurTask, ClearMode, RenderTaskLocation, RenderTaskTree};
|
||||
use resource_cache::ResourceCache;
|
||||
use std::{cmp, usize, f32, i32};
|
||||
@ -404,6 +403,7 @@ impl RenderTarget for ColorRenderTarget {
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::CacheMask(..) => {
|
||||
panic!("Should not be added to color target!");
|
||||
}
|
||||
@ -480,7 +480,6 @@ impl RenderTarget for ColorRenderTarget {
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct AlphaRenderTarget {
|
||||
pub clip_batcher: ClipBatcher,
|
||||
pub brush_mask_rounded_rects: Vec<PrimitiveInstance>,
|
||||
// List of blur operations to apply for this render target.
|
||||
pub vertical_blurs: Vec<BlurInstance>,
|
||||
pub horizontal_blurs: Vec<BlurInstance>,
|
||||
@ -500,7 +499,6 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
) -> Self {
|
||||
AlphaRenderTarget {
|
||||
clip_batcher: ClipBatcher::new(),
|
||||
brush_mask_rounded_rects: Vec::new(),
|
||||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
scalings: Vec::new(),
|
||||
@ -532,6 +530,7 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
|
||||
match task.kind {
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::Blit(..) => {
|
||||
panic!("BUG: should not be added to alpha target!");
|
||||
}
|
||||
@ -553,73 +552,6 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::Picture(ref task_info) => {
|
||||
let prim_metadata = ctx.prim_store.get_metadata(task_info.prim_index);
|
||||
|
||||
match prim_metadata.prim_kind {
|
||||
PrimitiveKind::Picture => {
|
||||
let prim = &ctx.prim_store.cpu_pictures[prim_metadata.cpu_prim_index.0];
|
||||
|
||||
let task_index = render_tasks.get_task_address(task_id);
|
||||
|
||||
for run in &prim.runs {
|
||||
for i in 0 .. run.count {
|
||||
let sub_prim_index = PrimitiveIndex(run.base_prim_index.0 + i);
|
||||
|
||||
let sub_metadata = ctx.prim_store.get_metadata(sub_prim_index);
|
||||
let sub_prim_address =
|
||||
gpu_cache.get_address(&sub_metadata.gpu_location);
|
||||
|
||||
match sub_metadata.prim_kind {
|
||||
PrimitiveKind::Brush => {
|
||||
let instance = BrushInstance {
|
||||
picture_address: task_index,
|
||||
prim_address: sub_prim_address,
|
||||
// TODO(gw): In the future, when brush
|
||||
// primitives on picture backed
|
||||
// tasks support clip masks and
|
||||
// transform primitives, these
|
||||
// will need to be filled out!
|
||||
clip_chain_rect_index: ClipChainRectIndex(0),
|
||||
scroll_id: GPUClipScrollNodeIndex(0),
|
||||
clip_task_address: RenderTaskAddress(0),
|
||||
z: 0,
|
||||
segment_index: 0,
|
||||
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
user_data: [0; 3],
|
||||
};
|
||||
let brush = &ctx.prim_store.cpu_brushes[sub_metadata.cpu_prim_index.0];
|
||||
let batch = match brush.kind {
|
||||
BrushKind::Solid { .. } |
|
||||
BrushKind::Clear |
|
||||
BrushKind::Picture |
|
||||
BrushKind::Line { .. } |
|
||||
BrushKind::YuvImage { .. } |
|
||||
BrushKind::RadialGradient { .. } |
|
||||
BrushKind::LinearGradient { .. } |
|
||||
BrushKind::Image { .. } => {
|
||||
unreachable!("bug: unexpected brush here");
|
||||
}
|
||||
BrushKind::Mask { .. } => {
|
||||
&mut self.brush_mask_rounded_rects
|
||||
}
|
||||
};
|
||||
batch.push(PrimitiveInstance::from(instance));
|
||||
}
|
||||
_ => {
|
||||
unreachable!("Unexpected sub primitive type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// No other primitives make use of primitive caching yet!
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderTaskKind::CacheMask(ref task_info) => {
|
||||
let task_address = render_tasks.get_task_address(task_id);
|
||||
self.clip_batcher.add(
|
||||
@ -631,6 +563,13 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
clip_store,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::ClipRegion(ref task) => {
|
||||
let task_address = render_tasks.get_task_address(task_id);
|
||||
self.clip_batcher.add_clip_region(
|
||||
task_address,
|
||||
task.clip_data_address,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
self.scalings.push(ScalingInfo {
|
||||
src_task_id: task.children[0],
|
||||
@ -704,6 +643,7 @@ impl TextureCacheRenderTarget {
|
||||
}
|
||||
RenderTaskKind::VerticalBlur(..) |
|
||||
RenderTaskKind::Picture(..) |
|
||||
RenderTaskKind::ClipRegion(..) |
|
||||
RenderTaskKind::CacheMask(..) |
|
||||
RenderTaskKind::Readback(..) |
|
||||
RenderTaskKind::Scaling(..) => {
|
||||
@ -801,10 +741,9 @@ impl RenderPass {
|
||||
}
|
||||
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 task = &render_tasks[task_id];
|
||||
task.is_shared() &&
|
||||
task.target_kind() == RenderTargetKind::Alpha
|
||||
});
|
||||
let saved_color = if self.tasks.iter().any(|&task_id| {
|
||||
let t = &render_tasks[task_id];
|
||||
|
@ -32,6 +32,10 @@ const SHADERS: &[Shader] = &[
|
||||
name: "cs_clip_image",
|
||||
features: CLIP_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "cs_clip_box_shadow",
|
||||
features: CLIP_FEATURES,
|
||||
},
|
||||
Shader {
|
||||
name: "cs_clip_border",
|
||||
features: CLIP_FEATURES,
|
||||
@ -83,10 +87,6 @@ const SHADERS: &[Shader] = &[
|
||||
name: "brush_solid",
|
||||
features: &[],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_picture",
|
||||
features: &[],
|
||||
},
|
||||
Shader {
|
||||
name: "brush_blend",
|
||||
features: &[],
|
||||
|
@ -1 +1 @@
|
||||
0da6c839b3a0e165f1115fb9fe286be7540c24ed
|
||||
5cb71f0f23719795e7c89417d91a7abad8ac20e9
|
||||
|
Loading…
Reference in New Issue
Block a user