mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-09 16:57:36 +00:00
Bug 1409736 - Update webrender to commit d741f472dd3d6c3441646f7bf4e714c71bea39b7. r=jrmuizel
MozReview-Commit-ID: FhFX2PAHwU --HG-- extra : rebase_source : 34c2d4bedadc940cf4a16dbdd6e0755eee909889
This commit is contained in:
parent
20baeb4811
commit
5e25afb9c5
@ -175,4 +175,4 @@ Troubleshooting tips:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The version of WebRender currently in the tree is:
|
||||
7892f5364bc4d35c7a9b42949f0ace4cc54f8b3c
|
||||
d741f472dd3d6c3441646f7bf4e714c71bea39b7
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "webrender"
|
||||
version = "0.52.1"
|
||||
version = "0.53.0"
|
||||
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/servo/webrender"
|
||||
|
@ -218,7 +218,11 @@ impl Example for App {
|
||||
rect: (75, 75).by(100, 100),
|
||||
repeat: false,
|
||||
};
|
||||
let complex = ComplexClipRegion::new((50, 50).to(150, 150), BorderRadius::uniform(20.0));
|
||||
let complex = ComplexClipRegion::new(
|
||||
(50, 50).to(150, 150),
|
||||
BorderRadius::uniform(20.0),
|
||||
ClipMode::Clip
|
||||
);
|
||||
let id = builder.define_clip(None, bounds, vec![complex], Some(mask));
|
||||
builder.push_clip_id(id);
|
||||
|
||||
@ -339,7 +343,7 @@ impl Example for App {
|
||||
color,
|
||||
blur_radius,
|
||||
spread_radius,
|
||||
simple_border_radius,
|
||||
BorderRadius::uniform(simple_border_radius),
|
||||
box_shadow_type,
|
||||
);
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use webrender::api::{self, DisplayListBuilder, DocumentId, LayoutSize, PipelineId, RenderApi,
|
||||
ResourceUpdates};
|
||||
use webrender::api::{self, DeviceUintRect, DisplayListBuilder, DocumentId, LayoutSize, PipelineId,
|
||||
RenderApi, ResourceUpdates};
|
||||
|
||||
// This example shows how to implement a very basic BlobImageRenderer that can only render
|
||||
// a checkerboard pattern.
|
||||
@ -145,7 +145,7 @@ impl api::BlobImageRenderer for CheckerboardRenderer {
|
||||
.insert(key, Arc::new(deserialize_blob(&cmds[..]).unwrap()));
|
||||
}
|
||||
|
||||
fn update(&mut self, key: api::ImageKey, cmds: api::BlobImageData) {
|
||||
fn update(&mut self, key: api::ImageKey, cmds: api::BlobImageData, _dirty_rect: Option<DeviceUintRect>) {
|
||||
// Here, updating is just replacing the current version of the commands with
|
||||
// the new one (no incremental updates).
|
||||
self.image_cmds
|
||||
|
@ -22,12 +22,18 @@ impl Notifier {
|
||||
}
|
||||
|
||||
impl RenderNotifier for Notifier {
|
||||
fn new_frame_ready(&mut self) {
|
||||
fn clone(&self) -> Box<RenderNotifier> {
|
||||
Box::new(Notifier {
|
||||
window_proxy: self.window_proxy.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn new_frame_ready(&self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.window_proxy.wakeup_event_loop();
|
||||
}
|
||||
|
||||
fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {
|
||||
fn new_scroll_frame_ready(&self, _composite_needed: bool) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.window_proxy.wakeup_event_loop();
|
||||
}
|
||||
@ -125,13 +131,11 @@ pub fn main_wrapper(example: &mut Example, options: Option<webrender::RendererOp
|
||||
};
|
||||
|
||||
let size = DeviceUintSize::new(width, height);
|
||||
let (mut renderer, sender) = webrender::Renderer::new(gl.clone(), opts).unwrap();
|
||||
let notifier = Box::new(Notifier::new(window.create_window_proxy()));
|
||||
let (mut renderer, sender) = webrender::Renderer::new(gl.clone(), notifier, opts).unwrap();
|
||||
let api = sender.create_api();
|
||||
let document_id = api.add_document(size);
|
||||
|
||||
let notifier = Box::new(Notifier::new(window.create_window_proxy()));
|
||||
renderer.set_render_notifier(notifier);
|
||||
|
||||
if let Some(external_image_handler) = example.get_external_image_handler() {
|
||||
renderer.set_external_image_handler(external_image_handler);
|
||||
}
|
||||
|
@ -14,12 +14,15 @@ flat varying vec4 vClipCenter_Radius_BL;
|
||||
|
||||
struct BrushPrimitive {
|
||||
float clip_mode;
|
||||
float radius;
|
||||
vec2 radius_tl;
|
||||
vec2 radius_tr;
|
||||
vec2 radius_br;
|
||||
vec2 radius_bl;
|
||||
};
|
||||
|
||||
BrushPrimitive fetch_brush_primitive(int address) {
|
||||
vec4 data = fetch_from_resource_cache_1(address);
|
||||
return BrushPrimitive(data.x, data.y);
|
||||
vec4 data[3] = fetch_from_resource_cache_3(address);
|
||||
return BrushPrimitive(data[0].x, data[1].xy, data[1].zw, data[2].xy, data[2].zw);
|
||||
}
|
||||
|
||||
void brush_vs(int prim_address, vec4 prim_rect) {
|
||||
@ -29,11 +32,10 @@ void brush_vs(int prim_address, vec4 prim_rect) {
|
||||
// Write clip parameters
|
||||
vClipMode = prim.clip_mode;
|
||||
|
||||
vec2 r = vec2(prim.radius);
|
||||
vClipCenter_Radius_TL = vec4(prim_rect.xy + vec2(r.x, r.y), r);
|
||||
vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-r.x, r.y), r);
|
||||
vClipCenter_Radius_BR = vec4(prim_rect.zw + vec2(-r.x, -r.y), r);
|
||||
vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(r.x, -r.y), r);
|
||||
vClipCenter_Radius_TL = vec4(prim_rect.xy + prim.radius_tl, prim.radius_tl);
|
||||
vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-prim.radius_tr.x, prim.radius_tr.y), prim.radius_tr);
|
||||
vClipCenter_Radius_BR = vec4(prim_rect.zw - prim.radius_br, prim.radius_br);
|
||||
vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(prim.radius_bl.x, -prim.radius_bl.y), prim.radius_bl);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -20,16 +20,14 @@ flat varying int vBlurRadius;
|
||||
in int aBlurRenderTaskAddress;
|
||||
in int aBlurSourceTaskAddress;
|
||||
in int aBlurDirection;
|
||||
in vec4 aBlurRegion;
|
||||
|
||||
void main(void) {
|
||||
RenderTaskData task = fetch_render_task(aBlurRenderTaskAddress);
|
||||
RenderTaskData src_task = fetch_render_task(aBlurSourceTaskAddress);
|
||||
|
||||
vec4 local_rect = task.data0;
|
||||
|
||||
vec2 pos = mix(local_rect.xy,
|
||||
local_rect.xy + local_rect.zw,
|
||||
aPosition.xy);
|
||||
vec4 src_rect = src_task.data0;
|
||||
vec4 target_rect = task.data0;
|
||||
|
||||
#if defined WR_FEATURE_COLOR
|
||||
vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0).xy);
|
||||
@ -49,12 +47,20 @@ void main(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
vUvRect = vec4(src_task.data0.xy + vec2(0.5),
|
||||
src_task.data0.xy + src_task.data0.zw - vec2(0.5));
|
||||
vUvRect = vec4(src_rect.xy + vec2(0.5),
|
||||
src_rect.xy + src_rect.zw - vec2(0.5));
|
||||
vUvRect /= texture_size.xyxy;
|
||||
|
||||
vec2 uv0 = src_task.data0.xy / texture_size;
|
||||
vec2 uv1 = (src_task.data0.xy + src_task.data0.zw) / texture_size;
|
||||
if (aBlurRegion.z > 0.0) {
|
||||
vec4 blur_region = aBlurRegion * uDevicePixelRatio;
|
||||
src_rect = vec4(src_rect.xy + blur_region.xy, blur_region.zw);
|
||||
target_rect = vec4(target_rect.xy + blur_region.xy, blur_region.zw);
|
||||
}
|
||||
|
||||
vec2 pos = target_rect.xy + target_rect.zw * aPosition.xy;
|
||||
|
||||
vec2 uv0 = src_rect.xy / texture_size;
|
||||
vec2 uv1 = (src_rect.xy + src_rect.zw) / texture_size;
|
||||
vUv.xy = mix(uv0, uv1, aPosition.xy);
|
||||
|
||||
gl_Position = uTransform * vec4(pos, 0.0, 1.0);
|
||||
|
@ -15,6 +15,7 @@ use util::{lerp, pack_as_float};
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum BorderCornerInstance {
|
||||
None,
|
||||
Single, // Single instance needed - corner styles are same or similar.
|
||||
Double, // Different corner styles. Draw two instances, one per style.
|
||||
}
|
||||
@ -128,8 +129,8 @@ impl NormalBorderHelpers for NormalBorder {
|
||||
corner: BorderCorner,
|
||||
border_rect: &LayerRect,
|
||||
) -> BorderCornerKind {
|
||||
// If either width is zero, a corner isn't formed.
|
||||
if width0 == 0.0 || width1 == 0.0 {
|
||||
// If both widths are zero, a corner isn't formed.
|
||||
if width0 == 0.0 && width1 == 0.0 {
|
||||
return BorderCornerKind::None;
|
||||
}
|
||||
|
||||
@ -139,9 +140,13 @@ impl NormalBorderHelpers for NormalBorder {
|
||||
}
|
||||
|
||||
match (edge0.style, edge1.style) {
|
||||
// If either edge is none or hidden, no corner is needed.
|
||||
(BorderStyle::None, _) | (_, BorderStyle::None) => BorderCornerKind::None,
|
||||
(BorderStyle::Hidden, _) | (_, BorderStyle::Hidden) => BorderCornerKind::None,
|
||||
// If both edges are none or hidden, no corner is needed.
|
||||
(BorderStyle::None, BorderStyle::None) |
|
||||
(BorderStyle::None, BorderStyle::Hidden) |
|
||||
(BorderStyle::Hidden, BorderStyle::None) |
|
||||
(BorderStyle::Hidden, BorderStyle::Hidden) => {
|
||||
BorderCornerKind::None
|
||||
}
|
||||
|
||||
// If both borders are solid, we can draw them with a simple rectangle if
|
||||
// both the colors match and there is no radius.
|
||||
@ -429,16 +434,19 @@ impl FrameBuilder {
|
||||
let mut corner_instances = [BorderCornerInstance::Single; 4];
|
||||
|
||||
for (i, corner) in corners.iter().enumerate() {
|
||||
match corner {
|
||||
&BorderCornerKind::Mask(corner_data, corner_radius, widths, kind) => {
|
||||
match *corner {
|
||||
BorderCornerKind::Mask(corner_data, corner_radius, widths, kind) => {
|
||||
let clip_source =
|
||||
BorderCornerClipSource::new(corner_data, corner_radius, widths, kind);
|
||||
extra_clips.push(ClipSource::BorderCorner(clip_source));
|
||||
}
|
||||
&BorderCornerKind::Clip(instance_kind) => {
|
||||
BorderCornerKind::Clip(instance_kind) => {
|
||||
corner_instances[i] = instance_kind;
|
||||
}
|
||||
_ => {}
|
||||
BorderCornerKind::Solid => {}
|
||||
BorderCornerKind::None => {
|
||||
corner_instances[i] = BorderCornerInstance::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, ImageRendering, LayerPoint};
|
||||
use api::{LayerRect, LayerSize, LayerToWorldTransform, LayoutPoint, LayoutVector2D, LocalClip};
|
||||
use api::{ClipMode, LayerRect, LayerSize};
|
||||
use api::{LayerToWorldTransform, LayoutPoint, LayoutVector2D, LocalClip};
|
||||
use border::BorderCornerClipSource;
|
||||
use ellipse::Ellipse;
|
||||
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
|
||||
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
|
||||
use prim_store::{ClipData, ImageMaskData};
|
||||
use resource_cache::ResourceCache;
|
||||
use std::ops::Not;
|
||||
use util::{extract_inner_rect_safe, TransformedRect};
|
||||
|
||||
const MAX_CLIP: f32 = 1000000.0;
|
||||
@ -61,24 +61,6 @@ impl ClipRegion {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ClipMode {
|
||||
Clip, // Pixels inside the region are visible.
|
||||
ClipOut, // Pixels outside the region are visible.
|
||||
}
|
||||
|
||||
impl Not for ClipMode {
|
||||
type Output = ClipMode;
|
||||
|
||||
fn not(self) -> ClipMode {
|
||||
match self {
|
||||
ClipMode::Clip => ClipMode::ClipOut,
|
||||
ClipMode::ClipOut => ClipMode::Clip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ClipSource {
|
||||
Rectangle(LayerRect),
|
||||
@ -105,7 +87,7 @@ impl From<ClipRegion> for ClipSources {
|
||||
clips.push(ClipSource::RoundedRectangle(
|
||||
complex.rect,
|
||||
complex.radii,
|
||||
ClipMode::Clip,
|
||||
complex.mode,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ use api::{HitTestResult, ImageDisplayItem, ItemRange, LayerPoint, LayerPrimitive
|
||||
use api::{LayerSize, LayerToScrollTransform, LayerVector2D, LayoutSize, LayoutTransform};
|
||||
use api::{LocalClip, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLayerState};
|
||||
use api::{ScrollLocation, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem, StackingContext};
|
||||
use api::{TileOffset, TransformStyle, WorldPoint};
|
||||
use api::{ClipMode, TileOffset, TransformStyle, WorldPoint};
|
||||
use clip::ClipRegion;
|
||||
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
|
||||
use euclid::rect;
|
||||
@ -1151,7 +1151,12 @@ fn try_to_add_rectangle_splitting_on_clip(
|
||||
|
||||
let inner_unclipped_rect = match &info.local_clip {
|
||||
&LocalClip::Rect(_) => return false,
|
||||
&LocalClip::RoundedRect(_, ref region) => region.get_inner_rect_full(),
|
||||
&LocalClip::RoundedRect(_, ref region) => {
|
||||
if region.mode == ClipMode::ClipOut {
|
||||
return false;
|
||||
}
|
||||
region.get_inner_rect_full()
|
||||
}
|
||||
};
|
||||
let inner_unclipped_rect = match inner_unclipped_rect {
|
||||
Some(rect) => rect,
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, BuiltDisplayList};
|
||||
use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF};
|
||||
use api::{ClipMode, ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF, LayoutSize};
|
||||
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
|
||||
use api::{ExtendMode, FilterOp, FontInstance, FontRenderMode};
|
||||
use api::{GlyphInstance, GlyphOptions, GradientStop, HitTestFlags, HitTestItem, HitTestResult};
|
||||
@ -14,7 +14,7 @@ use api::{ScrollSensitivity, Shadow, TileOffset, TransformStyle};
|
||||
use api::{WorldPixel, WorldPoint, YuvColorSpace, YuvData, device_length};
|
||||
use app_units::Au;
|
||||
use border::ImageBorderSegment;
|
||||
use clip::{ClipMode, ClipRegion, ClipSource, ClipSources, ClipStore, Contains};
|
||||
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore, Contains};
|
||||
use clip_scroll_node::{ClipInfo, ClipScrollNode, NodeType};
|
||||
use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId};
|
||||
use euclid::{SideOffsets2D, TypedTransform3D, vec2, vec3};
|
||||
@ -29,7 +29,7 @@ use prim_store::{PrimitiveContainer, PrimitiveIndex};
|
||||
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu};
|
||||
use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu};
|
||||
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
|
||||
use render_task::{AlphaRenderItem, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation};
|
||||
use render_task::{AlphaRenderItem, ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation};
|
||||
use render_task::RenderTaskTree;
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::ScenePipeline;
|
||||
@ -40,6 +40,9 @@ use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, Ren
|
||||
use tiling::{RenderTargetContext, ScrollbarPrimitive, StackingContext};
|
||||
use util::{self, pack_as_float, RectHelpers, recycle_vec};
|
||||
|
||||
// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
|
||||
const BLUR_SAMPLE_SCALE: f32 = 3.0;
|
||||
|
||||
/// Construct a polygon from stacking context boundaries.
|
||||
/// `anchor` here is an index that's going to be preserved in all the
|
||||
/// splits of the polygon.
|
||||
@ -242,7 +245,7 @@ impl FrameBuilder {
|
||||
clip_sources.push(ClipSource::RoundedRectangle(
|
||||
region.rect,
|
||||
region.radii,
|
||||
ClipMode::Clip,
|
||||
region.mode,
|
||||
));
|
||||
}
|
||||
|
||||
@ -557,7 +560,7 @@ impl FrameBuilder {
|
||||
clip_and_scroll: ClipAndScrollInfo,
|
||||
info: &LayerPrimitiveInfo,
|
||||
) {
|
||||
let prim = PicturePrimitive::new_shadow(shadow, RenderTargetKind::Color);
|
||||
let prim = PicturePrimitive::new_text_shadow(shadow);
|
||||
|
||||
// Create an empty shadow primitive. Insert it into
|
||||
// the draw lists immediately so that it will be drawn
|
||||
@ -587,7 +590,7 @@ impl FrameBuilder {
|
||||
// is then used when blitting the shadow to the final location.
|
||||
let metadata = &mut self.prim_store.cpu_metadata[prim_index.0];
|
||||
let prim = &self.prim_store.cpu_pictures[metadata.cpu_prim_index.0];
|
||||
let shadow = prim.as_shadow();
|
||||
let shadow = prim.as_text_shadow();
|
||||
|
||||
metadata.local_rect = metadata.local_rect.translate(&shadow.offset);
|
||||
}
|
||||
@ -676,7 +679,7 @@ impl FrameBuilder {
|
||||
for (idx, &(shadow_prim_index, _)) in self.shadow_prim_stack.iter().enumerate() {
|
||||
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
|
||||
let picture = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
|
||||
let shadow = picture.as_shadow();
|
||||
let shadow = picture.as_text_shadow();
|
||||
if shadow.blur_radius == 0.0 {
|
||||
fast_shadow_prims.push((idx, shadow.clone()));
|
||||
}
|
||||
@ -719,7 +722,7 @@ impl FrameBuilder {
|
||||
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Picture);
|
||||
let picture =
|
||||
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
|
||||
let blur_radius = picture.as_shadow().blur_radius;
|
||||
let blur_radius = picture.as_text_shadow().blur_radius;
|
||||
|
||||
// Only run real blurs here (fast path zero blurs are handled above).
|
||||
if blur_radius > 0.0 {
|
||||
@ -1183,7 +1186,7 @@ impl FrameBuilder {
|
||||
for (idx, &(shadow_prim_index, _)) in self.shadow_prim_stack.iter().enumerate() {
|
||||
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
|
||||
let picture_prim = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
|
||||
let shadow = picture_prim.as_shadow();
|
||||
let shadow = picture_prim.as_text_shadow();
|
||||
if shadow.blur_radius == 0.0 {
|
||||
let mut text_prim = prim.clone();
|
||||
text_prim.font.color = shadow.color.into();
|
||||
@ -1238,7 +1241,7 @@ impl FrameBuilder {
|
||||
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
|
||||
|
||||
// Only run real blurs here (fast path zero blurs are handled above).
|
||||
let blur_radius = picture_prim.as_shadow().blur_radius;
|
||||
let blur_radius = picture_prim.as_text_shadow().blur_radius;
|
||||
if blur_radius > 0.0 {
|
||||
let shadow_rect = rect.inflate(
|
||||
blur_radius,
|
||||
@ -1258,7 +1261,7 @@ impl FrameBuilder {
|
||||
color: &ColorF,
|
||||
blur_radius: f32,
|
||||
spread_radius: f32,
|
||||
border_radius: f32,
|
||||
border_radius: BorderRadius,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
) {
|
||||
if color.a == 0.0 {
|
||||
@ -1274,15 +1277,11 @@ impl FrameBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
// Adjust the shadow box radius as per:
|
||||
// https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
|
||||
let sharpness_scale = if border_radius < spread_radius {
|
||||
let r = border_radius / spread_amount;
|
||||
1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
let shadow_radius = (border_radius + spread_amount * sharpness_scale).max(0.0);
|
||||
let shadow_radius = adjust_border_radius_for_box_shadow(
|
||||
border_radius,
|
||||
spread_amount,
|
||||
spread_radius
|
||||
);
|
||||
let shadow_rect = prim_info.rect
|
||||
.translate(box_offset)
|
||||
.inflate(spread_amount, spread_amount);
|
||||
@ -1295,7 +1294,7 @@ impl FrameBuilder {
|
||||
// TODO(gw): Add a fast path for ClipOut + zero border radius!
|
||||
clips.push(ClipSource::RoundedRectangle(
|
||||
prim_info.rect,
|
||||
BorderRadius::uniform(border_radius),
|
||||
border_radius,
|
||||
ClipMode::ClipOut
|
||||
));
|
||||
|
||||
@ -1303,14 +1302,18 @@ impl FrameBuilder {
|
||||
shadow_rect,
|
||||
LocalClip::RoundedRect(
|
||||
shadow_rect,
|
||||
ComplexClipRegion::new(shadow_rect, BorderRadius::uniform(shadow_radius)),
|
||||
ComplexClipRegion::new(
|
||||
shadow_rect,
|
||||
shadow_radius,
|
||||
ClipMode::Clip,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
clips.push(ClipSource::RoundedRectangle(
|
||||
shadow_rect,
|
||||
BorderRadius::uniform(shadow_radius),
|
||||
shadow_radius,
|
||||
ClipMode::ClipOut
|
||||
));
|
||||
|
||||
@ -1318,7 +1321,11 @@ impl FrameBuilder {
|
||||
prim_info.rect,
|
||||
LocalClip::RoundedRect(
|
||||
prim_info.rect,
|
||||
ComplexClipRegion::new(prim_info.rect, BorderRadius::uniform(border_radius)),
|
||||
ComplexClipRegion::new(
|
||||
prim_info.rect,
|
||||
border_radius,
|
||||
ClipMode::Clip
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -1333,17 +1340,11 @@ impl FrameBuilder {
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
let shadow = Shadow {
|
||||
blur_radius,
|
||||
color: *color,
|
||||
offset: LayerVector2D::zero(),
|
||||
};
|
||||
|
||||
let blur_offset = 2.0 * blur_radius;
|
||||
let mut extra_clips = vec![];
|
||||
let mut pic_prim = PicturePrimitive::new_shadow(shadow, RenderTargetKind::Alpha);
|
||||
let mut blur_regions = vec![];
|
||||
|
||||
let pic_info = match clip_mode {
|
||||
match clip_mode {
|
||||
BoxShadowClipMode::Outset => {
|
||||
let brush_prim = BrushPrimitive {
|
||||
clip_mode: ClipMode::Clip,
|
||||
@ -1362,16 +1363,72 @@ impl FrameBuilder {
|
||||
PrimitiveContainer::Brush(brush_prim),
|
||||
);
|
||||
|
||||
let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
|
||||
let blur_range = BLUR_SAMPLE_SCALE * blur_radius;
|
||||
|
||||
let size = pic_rect.size;
|
||||
|
||||
let tl = LayerSize::new(
|
||||
blur_radius.max(border_radius.top_left.width),
|
||||
blur_radius.max(border_radius.top_left.height)
|
||||
) * BLUR_SAMPLE_SCALE;
|
||||
let tr = LayerSize::new(
|
||||
blur_radius.max(border_radius.top_right.width),
|
||||
blur_radius.max(border_radius.top_right.height)
|
||||
) * BLUR_SAMPLE_SCALE;
|
||||
let br = LayerSize::new(
|
||||
blur_radius.max(border_radius.bottom_right.width),
|
||||
blur_radius.max(border_radius.bottom_right.height)
|
||||
) * BLUR_SAMPLE_SCALE;
|
||||
let bl = LayerSize::new(
|
||||
blur_radius.max(border_radius.bottom_left.width),
|
||||
blur_radius.max(border_radius.bottom_left.height)
|
||||
) * BLUR_SAMPLE_SCALE;
|
||||
|
||||
let max_width = tl.width.max(tr.width.max(bl.width.max(br.width)));
|
||||
let max_height = tl.height.max(tr.height.max(bl.height.max(br.height)));
|
||||
|
||||
// Apply a conservative test that if any of the blur regions below
|
||||
// will overlap, we won't bother applying the region optimization
|
||||
// and will just blur the entire thing. This should only happen
|
||||
// in rare cases, where either the blur radius or border radius
|
||||
// is very large, in which case there's no real point in trying
|
||||
// to only blur a small region anyway.
|
||||
if max_width < 0.5 * size.width && max_height < 0.5 * size.height {
|
||||
blur_regions.push(LayerRect::from_floats(0.0, 0.0, tl.width, tl.height));
|
||||
blur_regions.push(LayerRect::from_floats(size.width - tr.width, 0.0, size.width, tr.height));
|
||||
blur_regions.push(LayerRect::from_floats(size.width - br.width, size.height - br.height, size.width, size.height));
|
||||
blur_regions.push(LayerRect::from_floats(0.0, size.height - bl.height, bl.width, size.height));
|
||||
|
||||
blur_regions.push(LayerRect::from_floats(0.0, tl.height, blur_range, size.height - bl.height));
|
||||
blur_regions.push(LayerRect::from_floats(size.width - blur_range, tr.height, size.width, size.height - br.height));
|
||||
blur_regions.push(LayerRect::from_floats(tl.width, 0.0, size.width - tr.width, blur_range));
|
||||
blur_regions.push(LayerRect::from_floats(bl.width, size.height - blur_range, size.width - br.width, size.height));
|
||||
}
|
||||
|
||||
let mut pic_prim = PicturePrimitive::new_box_shadow(
|
||||
blur_radius,
|
||||
*color,
|
||||
blur_regions,
|
||||
BoxShadowClipMode::Outset,
|
||||
);
|
||||
|
||||
pic_prim.add_primitive(brush_prim_index, clip_and_scroll);
|
||||
|
||||
extra_clips.push(ClipSource::RoundedRectangle(
|
||||
prim_info.rect,
|
||||
BorderRadius::uniform(border_radius),
|
||||
border_radius,
|
||||
ClipMode::ClipOut,
|
||||
));
|
||||
|
||||
let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
|
||||
LayerPrimitiveInfo::new(pic_rect)
|
||||
let pic_info = LayerPrimitiveInfo::new(pic_rect);
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&pic_info,
|
||||
extra_clips,
|
||||
PrimitiveContainer::Picture(pic_prim),
|
||||
);
|
||||
}
|
||||
BoxShadowClipMode::Inset => {
|
||||
let brush_prim = BrushPrimitive {
|
||||
@ -1392,25 +1449,35 @@ impl FrameBuilder {
|
||||
PrimitiveContainer::Brush(brush_prim),
|
||||
);
|
||||
|
||||
let pic_rect = prim_info.rect.inflate(blur_offset, blur_offset);
|
||||
|
||||
// TODO(gw): Apply minimal blur regions for inset box shadows.
|
||||
|
||||
let mut pic_prim = PicturePrimitive::new_box_shadow(
|
||||
blur_radius,
|
||||
*color,
|
||||
blur_regions,
|
||||
BoxShadowClipMode::Inset,
|
||||
);
|
||||
|
||||
pic_prim.add_primitive(brush_prim_index, clip_and_scroll);
|
||||
|
||||
extra_clips.push(ClipSource::RoundedRectangle(
|
||||
prim_info.rect,
|
||||
BorderRadius::uniform(border_radius),
|
||||
border_radius,
|
||||
ClipMode::Clip,
|
||||
));
|
||||
|
||||
let pic_rect = prim_info.rect.inflate(blur_offset, blur_offset);
|
||||
LayerPrimitiveInfo::with_clip_rect(pic_rect, prim_info.rect)
|
||||
}
|
||||
};
|
||||
let pic_info = LayerPrimitiveInfo::with_clip_rect(pic_rect, prim_info.rect);
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&pic_info,
|
||||
extra_clips,
|
||||
PrimitiveContainer::Picture(pic_prim),
|
||||
);
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&pic_info,
|
||||
extra_clips,
|
||||
PrimitiveContainer::Picture(pic_prim),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1770,8 +1837,9 @@ impl FrameBuilder {
|
||||
|
||||
let transform = scroll_node.world_content_transform;
|
||||
if !packed_layer.set_transform(transform) {
|
||||
group.screen_bounding_rect = None;
|
||||
debug!("\t\tUnable to set transform {:?}", transform);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Here we move the viewport rectangle into the coordinate system
|
||||
@ -2045,6 +2113,8 @@ impl FrameBuilder {
|
||||
current_task_id,
|
||||
render_tasks,
|
||||
RenderTargetKind::Color,
|
||||
&[],
|
||||
ClearMode::Transparent,
|
||||
);
|
||||
let blur_render_task_id = render_tasks.add(blur_render_task);
|
||||
let item = AlphaRenderItem::HardwareComposite(
|
||||
@ -2326,3 +2396,67 @@ impl FrameBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_border_radius_for_box_shadow(
|
||||
radius: BorderRadius,
|
||||
spread_amount: f32,
|
||||
spread_radius: f32,
|
||||
) -> BorderRadius {
|
||||
BorderRadius {
|
||||
top_left: adjust_corner_for_box_shadow(
|
||||
radius.top_left,
|
||||
spread_radius,
|
||||
spread_amount,
|
||||
),
|
||||
top_right: adjust_corner_for_box_shadow(
|
||||
radius.top_right,
|
||||
spread_radius,
|
||||
spread_amount,
|
||||
),
|
||||
bottom_right: adjust_corner_for_box_shadow(
|
||||
radius.bottom_right,
|
||||
spread_radius,
|
||||
spread_amount,
|
||||
),
|
||||
bottom_left: adjust_corner_for_box_shadow(
|
||||
radius.bottom_left,
|
||||
spread_radius,
|
||||
spread_amount,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn adjust_corner_for_box_shadow(
|
||||
corner: LayoutSize,
|
||||
spread_amount: f32,
|
||||
spread_radius: f32,
|
||||
) -> LayoutSize {
|
||||
LayoutSize::new(
|
||||
adjust_radius_for_box_shadow(
|
||||
corner.width,
|
||||
spread_radius,
|
||||
spread_amount
|
||||
),
|
||||
adjust_radius_for_box_shadow(
|
||||
corner.height,
|
||||
spread_radius,
|
||||
spread_amount
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn adjust_radius_for_box_shadow(
|
||||
border_radius: f32,
|
||||
spread_amount: f32,
|
||||
spread_radius: f32,
|
||||
) -> f32 {
|
||||
// Adjust the shadow box radius as per:
|
||||
// https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
|
||||
let sharpness_scale = if border_radius < spread_radius {
|
||||
let r = border_radius / spread_amount;
|
||||
1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
(border_radius + spread_amount * sharpness_scale).max(0.0)
|
||||
}
|
||||
|
@ -2,6 +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::LayerRect;
|
||||
use gpu_cache::GpuCacheAddress;
|
||||
use render_task::RenderTaskAddress;
|
||||
use tiling::PackedLayerIndex;
|
||||
@ -18,7 +19,7 @@ impl From<PackedLayerIndex> for PackedLayerAddress {
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum BlurDirection {
|
||||
Horizontal = 0,
|
||||
Vertical,
|
||||
@ -30,6 +31,7 @@ pub struct BlurInstance {
|
||||
pub task_address: RenderTaskAddress,
|
||||
pub src_task_address: RenderTaskAddress,
|
||||
pub blur_direction: BlurDirection,
|
||||
pub region: LayerRect,
|
||||
}
|
||||
|
||||
/// A clipping primitive drawn into the clipping mask.
|
||||
|
@ -2,9 +2,12 @@
|
||||
* 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::{ClipAndScrollInfo, Shadow};
|
||||
use prim_store::PrimitiveIndex;
|
||||
use render_task::RenderTaskId;
|
||||
use api::{ColorF, ClipAndScrollInfo, device_length, DeviceIntSize};
|
||||
use api::{BoxShadowClipMode, LayerRect, Shadow};
|
||||
use frame_builder::PrimitiveContext;
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use prim_store::{PrimitiveIndex, PrimitiveMetadata};
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskId, RenderTaskTree};
|
||||
use tiling::RenderTargetKind;
|
||||
|
||||
/*
|
||||
@ -25,19 +28,23 @@ pub struct PrimitiveRun {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CompositeOp {
|
||||
Shadow(Shadow),
|
||||
|
||||
// TODO(gw): Support other composite ops, such
|
||||
// as blur, blend etc.
|
||||
pub enum PictureKind {
|
||||
TextShadow {
|
||||
shadow: Shadow,
|
||||
},
|
||||
BoxShadow {
|
||||
blur_radius: f32,
|
||||
color: ColorF,
|
||||
blur_regions: Vec<LayerRect>,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PicturePrimitive {
|
||||
pub prim_runs: Vec<PrimitiveRun>,
|
||||
pub composite_op: CompositeOp,
|
||||
pub render_task_id: Option<RenderTaskId>,
|
||||
pub kind: RenderTargetKind,
|
||||
pub kind: PictureKind,
|
||||
|
||||
// TODO(gw): Add a mode that specifies if this
|
||||
// picture should be rasterized in
|
||||
@ -45,21 +52,38 @@ pub struct PicturePrimitive {
|
||||
}
|
||||
|
||||
impl PicturePrimitive {
|
||||
pub fn new_shadow(
|
||||
shadow: Shadow,
|
||||
kind: RenderTargetKind,
|
||||
) -> PicturePrimitive {
|
||||
pub fn new_text_shadow(shadow: Shadow) -> PicturePrimitive {
|
||||
PicturePrimitive {
|
||||
prim_runs: Vec::new(),
|
||||
composite_op: CompositeOp::Shadow(shadow),
|
||||
render_task_id: None,
|
||||
kind,
|
||||
kind: PictureKind::TextShadow {
|
||||
shadow,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_shadow(&self) -> &Shadow {
|
||||
match self.composite_op {
|
||||
CompositeOp::Shadow(ref shadow) => shadow,
|
||||
pub fn new_box_shadow(
|
||||
blur_radius: f32,
|
||||
color: ColorF,
|
||||
blur_regions: Vec<LayerRect>,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
) -> PicturePrimitive {
|
||||
PicturePrimitive {
|
||||
prim_runs: Vec::new(),
|
||||
render_task_id: None,
|
||||
kind: PictureKind::BoxShadow {
|
||||
blur_radius,
|
||||
color,
|
||||
blur_regions,
|
||||
clip_mode,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_text_shadow(&self) -> &Shadow {
|
||||
match self.kind {
|
||||
PictureKind::TextShadow { ref shadow } => shadow,
|
||||
PictureKind::BoxShadow { .. } => panic!("bug: not a text shadow")
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,4 +106,83 @@ impl PicturePrimitive {
|
||||
clip_and_scroll,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn prepare_for_render(
|
||||
&mut self,
|
||||
prim_index: PrimitiveIndex,
|
||||
prim_metadata: &PrimitiveMetadata,
|
||||
prim_context: &PrimitiveContext,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
) {
|
||||
// This is a shadow element. Create a render task that will
|
||||
// render the text run to a target, and then apply a gaussian
|
||||
// blur to that text run in order to build the actual primitive
|
||||
// which will be blitted to the framebuffer.
|
||||
let cache_width =
|
||||
(prim_metadata.local_rect.size.width * prim_context.device_pixel_ratio).ceil() as i32;
|
||||
let cache_height =
|
||||
(prim_metadata.local_rect.size.height * prim_context.device_pixel_ratio).ceil() as i32;
|
||||
let cache_size = DeviceIntSize::new(cache_width, cache_height);
|
||||
|
||||
let (blur_radius, target_kind, blur_regions, clear_mode) = match self.kind {
|
||||
PictureKind::TextShadow { ref shadow } => {
|
||||
let dummy: &[LayerRect] = &[];
|
||||
(shadow.blur_radius, RenderTargetKind::Color, dummy, ClearMode::Transparent)
|
||||
}
|
||||
PictureKind::BoxShadow { blur_radius, clip_mode, ref blur_regions, .. } => {
|
||||
let clear_mode = match clip_mode {
|
||||
BoxShadowClipMode::Outset => ClearMode::One,
|
||||
BoxShadowClipMode::Inset => ClearMode::Zero,
|
||||
};
|
||||
(blur_radius, RenderTargetKind::Alpha, blur_regions.as_slice(), clear_mode)
|
||||
}
|
||||
};
|
||||
let blur_radius = device_length(blur_radius, prim_context.device_pixel_ratio);
|
||||
|
||||
let picture_task = RenderTask::new_picture(
|
||||
cache_size,
|
||||
prim_index,
|
||||
target_kind,
|
||||
);
|
||||
let picture_task_id = render_tasks.add(picture_task);
|
||||
let render_task = RenderTask::new_blur(
|
||||
blur_radius,
|
||||
picture_task_id,
|
||||
render_tasks,
|
||||
target_kind,
|
||||
blur_regions,
|
||||
clear_mode,
|
||||
);
|
||||
self.render_task_id = Some(render_tasks.add(render_task));
|
||||
}
|
||||
|
||||
pub fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
|
||||
match self.kind {
|
||||
PictureKind::TextShadow { ref shadow } => {
|
||||
request.push(shadow.color);
|
||||
request.push([
|
||||
shadow.offset.x,
|
||||
shadow.offset.y,
|
||||
shadow.blur_radius,
|
||||
0.0,
|
||||
]);
|
||||
}
|
||||
PictureKind::BoxShadow { blur_radius, color, .. } => {
|
||||
request.push(color);
|
||||
request.push([
|
||||
0.0,
|
||||
0.0,
|
||||
blur_radius,
|
||||
0.0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target_kind(&self) -> RenderTargetKind {
|
||||
match self.kind {
|
||||
PictureKind::TextShadow { .. } => RenderTargetKind::Color,
|
||||
PictureKind::BoxShadow { .. } => RenderTargetKind::Alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,13 @@
|
||||
* 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, BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect, DeviceIntSize};
|
||||
use api::{BorderRadius, BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect};
|
||||
use api::{DevicePoint, ExtendMode, FontInstance, FontRenderMode, GlyphInstance, GlyphKey};
|
||||
use api::{GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerRect};
|
||||
use api::{LayerSize, LayerVector2D, LineOrientation, LineStyle};
|
||||
use api::{TileOffset, YuvColorSpace, YuvFormat, device_length};
|
||||
use api::{ClipMode, LayerSize, LayerVector2D, LineOrientation, LineStyle};
|
||||
use api::{TileOffset, YuvColorSpace, YuvFormat};
|
||||
use border::BorderCornerInstance;
|
||||
use clip::{ClipMode, ClipSourcesHandle, ClipStore, Geometry};
|
||||
use clip::{ClipSourcesHandle, ClipStore, Geometry};
|
||||
use frame_builder::PrimitiveContext;
|
||||
use gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest,
|
||||
ToGpuBlocks};
|
||||
@ -167,17 +167,29 @@ impl ToGpuBlocks for RectanglePrimitive {
|
||||
#[derive(Debug)]
|
||||
pub struct BrushPrimitive {
|
||||
pub clip_mode: ClipMode,
|
||||
pub radius: f32,
|
||||
pub radius: BorderRadius,
|
||||
}
|
||||
|
||||
impl ToGpuBlocks for BrushPrimitive {
|
||||
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
|
||||
request.push([
|
||||
self.clip_mode as u32 as f32,
|
||||
self.radius,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
]);
|
||||
request.push([
|
||||
self.radius.top_left.width,
|
||||
self.radius.top_left.height,
|
||||
self.radius.top_right.width,
|
||||
self.radius.top_right.height,
|
||||
]);
|
||||
request.push([
|
||||
self.radius.bottom_right.width,
|
||||
self.radius.bottom_right.height,
|
||||
self.radius.bottom_left.width,
|
||||
self.radius.bottom_left.height,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1037,46 +1049,20 @@ impl PrimitiveStore {
|
||||
prim_context: &PrimitiveContext,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
// For some primitives, we need to mark dependencies as needed for rendering
|
||||
// without spawning new tasks, since there will be another call to
|
||||
// `prepare_prim_for_render_inner` specifically for this primitive later on.
|
||||
render_tasks: Option<&mut RenderTaskTree>,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
text_run_mode: TextRunMode,
|
||||
) {
|
||||
let metadata = &mut self.cpu_metadata[prim_index.0];
|
||||
match metadata.prim_kind {
|
||||
PrimitiveKind::Rectangle | PrimitiveKind::Border | PrimitiveKind::Line => {}
|
||||
PrimitiveKind::Picture => {
|
||||
let picture = &mut self.cpu_pictures[metadata.cpu_prim_index.0];
|
||||
|
||||
// This is a shadow element. Create a render task that will
|
||||
// render the text run to a target, and then apply a gaussian
|
||||
// blur to that text run in order to build the actual primitive
|
||||
// which will be blitted to the framebuffer.
|
||||
let cache_width =
|
||||
(metadata.local_rect.size.width * prim_context.device_pixel_ratio).ceil() as i32;
|
||||
let cache_height =
|
||||
(metadata.local_rect.size.height * prim_context.device_pixel_ratio).ceil() as i32;
|
||||
let cache_size = DeviceIntSize::new(cache_width, cache_height);
|
||||
let blur_radius = picture.as_shadow().blur_radius;
|
||||
let blur_radius = device_length(blur_radius, prim_context.device_pixel_ratio);
|
||||
|
||||
// ignore new tasks if we are in a dependency context
|
||||
picture.render_task_id = render_tasks.map(|rt| {
|
||||
let picture_task = RenderTask::new_picture(
|
||||
cache_size,
|
||||
self.cpu_pictures[metadata.cpu_prim_index.0]
|
||||
.prepare_for_render(
|
||||
prim_index,
|
||||
picture.kind,
|
||||
metadata,
|
||||
prim_context,
|
||||
render_tasks
|
||||
);
|
||||
let picture_task_id = rt.add(picture_task);
|
||||
let render_task = RenderTask::new_blur(
|
||||
blur_radius,
|
||||
picture_task_id,
|
||||
rt,
|
||||
picture.kind
|
||||
);
|
||||
rt.add(render_task)
|
||||
});
|
||||
}
|
||||
PrimitiveKind::TextRun => {
|
||||
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
|
||||
@ -1173,15 +1159,8 @@ impl PrimitiveStore {
|
||||
text.write_gpu_blocks(&mut request);
|
||||
}
|
||||
PrimitiveKind::Picture => {
|
||||
let picture = &self.cpu_pictures[metadata.cpu_prim_index.0];
|
||||
let shadow = picture.as_shadow();
|
||||
request.push(shadow.color);
|
||||
request.push([
|
||||
shadow.offset.x,
|
||||
shadow.offset.y,
|
||||
shadow.blur_radius,
|
||||
0.0,
|
||||
]);
|
||||
self.cpu_pictures[metadata.cpu_prim_index.0]
|
||||
.write_gpu_blocks(request);
|
||||
}
|
||||
PrimitiveKind::Brush => {
|
||||
let brush = &self.cpu_brushes[metadata.cpu_prim_index.0];
|
||||
@ -1342,7 +1321,7 @@ impl PrimitiveStore {
|
||||
prim_context,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
None,
|
||||
render_tasks,
|
||||
TextRunMode::Shadow,
|
||||
);
|
||||
}
|
||||
@ -1365,7 +1344,7 @@ impl PrimitiveStore {
|
||||
prim_context,
|
||||
resource_cache,
|
||||
gpu_cache,
|
||||
Some(render_tasks),
|
||||
render_tasks,
|
||||
TextRunMode::Normal,
|
||||
);
|
||||
|
||||
|
@ -22,7 +22,8 @@ use resource_cache::ResourceCache;
|
||||
use scene::Scene;
|
||||
#[cfg(feature = "debugger")]
|
||||
use serde_json;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::u32;
|
||||
use texture_cache::TextureCache;
|
||||
@ -124,6 +125,9 @@ enum DocumentOp {
|
||||
Rendered(RendererFrame),
|
||||
}
|
||||
|
||||
/// The unique id for WR resource identification.
|
||||
static NEXT_NAMESPACE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
/// The render backend is responsible for transforming high level display lists into
|
||||
/// GPU-friendly work which is then submitted to the renderer in the form of a frame::Frame.
|
||||
///
|
||||
@ -133,7 +137,6 @@ pub struct RenderBackend {
|
||||
payload_rx: PayloadReceiver,
|
||||
payload_tx: PayloadSender,
|
||||
result_tx: Sender<ResultMsg>,
|
||||
next_namespace_id: IdNamespace,
|
||||
default_device_pixel_ratio: f32,
|
||||
|
||||
gpu_cache: GpuCache,
|
||||
@ -142,7 +145,7 @@ pub struct RenderBackend {
|
||||
frame_config: FrameBuilderConfig,
|
||||
documents: FastHashMap<DocumentId, Document>,
|
||||
|
||||
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
|
||||
notifier: Box<RenderNotifier>,
|
||||
recorder: Option<Box<ApiRecordingReceiver>>,
|
||||
|
||||
enable_render_on_scroll: bool,
|
||||
@ -157,12 +160,15 @@ impl RenderBackend {
|
||||
default_device_pixel_ratio: f32,
|
||||
texture_cache: TextureCache,
|
||||
workers: Arc<ThreadPool>,
|
||||
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
|
||||
notifier: Box<RenderNotifier>,
|
||||
frame_config: FrameBuilderConfig,
|
||||
recorder: Option<Box<ApiRecordingReceiver>>,
|
||||
blob_image_renderer: Option<Box<BlobImageRenderer>>,
|
||||
enable_render_on_scroll: bool,
|
||||
) -> RenderBackend {
|
||||
// The namespace_id should start from 1.
|
||||
NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let resource_cache = ResourceCache::new(texture_cache, workers, blob_image_renderer);
|
||||
|
||||
register_thread_with_profiler("Backend".to_string());
|
||||
@ -177,7 +183,6 @@ impl RenderBackend {
|
||||
gpu_cache: GpuCache::new(),
|
||||
frame_config,
|
||||
documents: FastHashMap::default(),
|
||||
next_namespace_id: IdNamespace(1),
|
||||
notifier,
|
||||
recorder,
|
||||
|
||||
@ -421,6 +426,10 @@ impl RenderBackend {
|
||||
}
|
||||
}
|
||||
|
||||
fn next_namespace_id(&self) -> IdNamespace {
|
||||
IdNamespace(NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed) as u32)
|
||||
}
|
||||
|
||||
pub fn run(&mut self, mut profile_counters: BackendProfileCounters) {
|
||||
let mut frame_counter: u32 = 0;
|
||||
|
||||
@ -435,8 +444,7 @@ impl RenderBackend {
|
||||
msg
|
||||
}
|
||||
Err(..) => {
|
||||
let notifier = self.notifier.lock();
|
||||
notifier.unwrap().as_mut().unwrap().shut_down();
|
||||
self.notifier.shut_down();
|
||||
break;
|
||||
}
|
||||
};
|
||||
@ -463,9 +471,7 @@ impl RenderBackend {
|
||||
tx.send(glyph_indices).unwrap();
|
||||
}
|
||||
ApiMsg::CloneApi(sender) => {
|
||||
let namespace = self.next_namespace_id;
|
||||
self.next_namespace_id = IdNamespace(namespace.0 + 1);
|
||||
sender.send(namespace).unwrap();
|
||||
sender.send(self.next_namespace_id()).unwrap();
|
||||
}
|
||||
ApiMsg::AddDocument(document_id, initial_size) => {
|
||||
let document = Document::new(
|
||||
@ -504,8 +510,7 @@ impl RenderBackend {
|
||||
self.documents.remove(&document_id);
|
||||
}
|
||||
ApiMsg::ExternalEvent(evt) => {
|
||||
let notifier = self.notifier.lock();
|
||||
notifier.unwrap().as_mut().unwrap().external_event(evt);
|
||||
self.notifier.external_event(evt);
|
||||
}
|
||||
ApiMsg::ClearNamespace(namespace_id) => {
|
||||
self.resource_cache.clear_namespace(namespace_id);
|
||||
@ -530,12 +535,7 @@ impl RenderBackend {
|
||||
// We use new_frame_ready to wake up the renderer and get the
|
||||
// resource updates processed, but the UpdateResources message
|
||||
// will cancel rendering the frame.
|
||||
self.notifier
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.new_frame_ready();
|
||||
self.notifier.new_frame_ready();
|
||||
}
|
||||
ApiMsg::DebugCommand(option) => {
|
||||
let msg = match option {
|
||||
@ -550,12 +550,10 @@ impl RenderBackend {
|
||||
_ => ResultMsg::DebugCommand(option),
|
||||
};
|
||||
self.result_tx.send(msg).unwrap();
|
||||
let notifier = self.notifier.lock();
|
||||
notifier.unwrap().as_mut().unwrap().new_frame_ready();
|
||||
self.notifier.new_frame_ready();
|
||||
}
|
||||
ApiMsg::ShutDown => {
|
||||
let notifier = self.notifier.lock();
|
||||
notifier.unwrap().as_mut().unwrap().shut_down();
|
||||
self.notifier.shut_down();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -582,31 +580,11 @@ impl RenderBackend {
|
||||
) {
|
||||
self.publish_frame(document_id, frame, profile_counters);
|
||||
|
||||
// TODO(gw): This is kindof bogus to have to lock the notifier
|
||||
// each time it's used. This is due to some nastiness
|
||||
// in initialization order for Servo. Perhaps find a
|
||||
// cleaner way to do this, or use the OnceMutex on crates.io?
|
||||
let mut notifier = self.notifier.lock();
|
||||
notifier
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.new_frame_ready();
|
||||
self.notifier.new_frame_ready();
|
||||
}
|
||||
|
||||
fn notify_compositor_of_new_scroll_frame(&mut self, composite_needed: bool) {
|
||||
// TODO(gw): This is kindof bogus to have to lock the notifier
|
||||
// each time it's used. This is due to some nastiness
|
||||
// in initialization order for Servo. Perhaps find a
|
||||
// cleaner way to do this, or use the OnceMutex on crates.io?
|
||||
let mut notifier = self.notifier.lock();
|
||||
notifier
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.new_scroll_frame_ready(composite_needed);
|
||||
fn notify_compositor_of_new_scroll_frame(&self, composite_needed: bool) {
|
||||
self.notifier.new_scroll_frame_ready(composite_needed);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use api::{ClipId, DeviceIntLength, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{FilterOp, MixBlendMode};
|
||||
use api::PipelineId;
|
||||
use api::{LayerRect, PipelineId};
|
||||
use clip::{ClipSource, ClipSourcesWeakHandle, ClipStore};
|
||||
use clip_scroll_tree::CoordinateSystemId;
|
||||
use gpu_cache::GpuCacheHandle;
|
||||
@ -264,6 +264,7 @@ pub struct PictureTask {
|
||||
pub struct BlurTask {
|
||||
pub blur_radius: DeviceIntLength,
|
||||
pub target_kind: RenderTargetKind,
|
||||
pub regions: Vec<LayerRect>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -282,12 +283,23 @@ pub enum RenderTaskKind {
|
||||
Alias(RenderTaskId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ClearMode {
|
||||
// Applicable to color and alpha targets.
|
||||
Zero,
|
||||
One,
|
||||
|
||||
// Applicable to color targets only.
|
||||
Transparent,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RenderTask {
|
||||
pub cache_key: Option<RenderTaskKey>,
|
||||
pub location: RenderTaskLocation,
|
||||
pub children: Vec<RenderTaskId>,
|
||||
pub kind: RenderTaskKind,
|
||||
pub clear_mode: ClearMode,
|
||||
}
|
||||
|
||||
impl RenderTask {
|
||||
@ -305,6 +317,7 @@ impl RenderTask {
|
||||
items: Vec::new(),
|
||||
frame_output_pipeline_id,
|
||||
}),
|
||||
clear_mode: ClearMode::Transparent,
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,6 +334,11 @@ impl RenderTask {
|
||||
prim_index: PrimitiveIndex,
|
||||
target_kind: RenderTargetKind,
|
||||
) -> RenderTask {
|
||||
let clear_mode = match target_kind {
|
||||
RenderTargetKind::Color => ClearMode::Transparent,
|
||||
RenderTargetKind::Alpha => ClearMode::One,
|
||||
};
|
||||
|
||||
RenderTask {
|
||||
cache_key: None,
|
||||
children: Vec::new(),
|
||||
@ -329,6 +347,7 @@ impl RenderTask {
|
||||
prim_index,
|
||||
target_kind,
|
||||
}),
|
||||
clear_mode,
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,6 +357,7 @@ impl RenderTask {
|
||||
children: Vec::new(),
|
||||
location: RenderTaskLocation::Dynamic(None, screen_rect.size),
|
||||
kind: RenderTaskKind::Readback(screen_rect),
|
||||
clear_mode: ClearMode::Transparent,
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,6 +440,7 @@ impl RenderTask {
|
||||
geometry_kind,
|
||||
coordinate_system_id: prim_coordinate_system_id,
|
||||
}),
|
||||
clear_mode: ClearMode::One,
|
||||
})
|
||||
}
|
||||
|
||||
@ -443,6 +464,8 @@ impl RenderTask {
|
||||
src_task_id: RenderTaskId,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
target_kind: RenderTargetKind,
|
||||
regions: &[LayerRect],
|
||||
clear_mode: ClearMode,
|
||||
) -> RenderTask {
|
||||
let blur_target_size = render_tasks.get(src_task_id).get_dynamic_size();
|
||||
|
||||
@ -453,7 +476,9 @@ impl RenderTask {
|
||||
kind: RenderTaskKind::VerticalBlur(BlurTask {
|
||||
blur_radius,
|
||||
target_kind,
|
||||
regions: regions.to_vec(),
|
||||
}),
|
||||
clear_mode,
|
||||
};
|
||||
|
||||
let blur_task_v_id = render_tasks.add(blur_task_v);
|
||||
@ -465,7 +490,9 @@ impl RenderTask {
|
||||
kind: RenderTaskKind::HorizontalBlur(BlurTask {
|
||||
blur_radius,
|
||||
target_kind,
|
||||
regions: regions.to_vec(),
|
||||
}),
|
||||
clear_mode,
|
||||
};
|
||||
|
||||
blur_task_h
|
||||
|
@ -55,7 +55,7 @@ use std::f32;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::thread;
|
||||
use texture_cache::TextureCache;
|
||||
@ -325,6 +325,11 @@ const DESC_BLUR: VertexDescriptor = VertexDescriptor {
|
||||
count: 1,
|
||||
kind: VertexAttributeKind::I32,
|
||||
},
|
||||
VertexAttribute {
|
||||
name: "aBlurRegion",
|
||||
count: 4,
|
||||
kind: VertexAttributeKind::F32
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -925,20 +930,14 @@ struct PrimitiveShader {
|
||||
}
|
||||
|
||||
struct FileWatcher {
|
||||
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
|
||||
notifier: Box<RenderNotifier>,
|
||||
result_tx: Sender<ResultMsg>,
|
||||
}
|
||||
|
||||
impl FileWatcherHandler for FileWatcher {
|
||||
fn file_changed(&self, path: PathBuf) {
|
||||
self.result_tx.send(ResultMsg::RefreshShader(path)).ok();
|
||||
let mut notifier = self.notifier.lock();
|
||||
notifier
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.new_frame_ready();
|
||||
self.notifier.new_frame_ready();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1132,8 +1131,6 @@ pub struct Renderer {
|
||||
ps_split_composite: LazilyCompiledShader,
|
||||
ps_composite: LazilyCompiledShader,
|
||||
|
||||
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
|
||||
|
||||
max_texture_size: u32,
|
||||
|
||||
max_recorded_profiles: usize,
|
||||
@ -1229,6 +1226,7 @@ impl Renderer {
|
||||
/// [rendereroptions]: struct.RendererOptions.html
|
||||
pub fn new(
|
||||
gl: Rc<gl::Gl>,
|
||||
notifier: Box<RenderNotifier>,
|
||||
mut options: RendererOptions,
|
||||
) -> Result<(Renderer, RenderApiSender), RendererError> {
|
||||
let (api_tx, api_rx) = try!{ channel::msg_channel() };
|
||||
@ -1236,12 +1234,11 @@ impl Renderer {
|
||||
let (result_tx, result_rx) = channel();
|
||||
let gl_type = gl.get_type();
|
||||
|
||||
let notifier = Arc::new(Mutex::new(None));
|
||||
let debug_server = DebugServer::new(api_tx.clone());
|
||||
|
||||
let file_watch_handler = FileWatcher {
|
||||
result_tx: result_tx.clone(),
|
||||
notifier: Arc::clone(¬ifier),
|
||||
notifier: notifier.clone(),
|
||||
};
|
||||
|
||||
let mut device = Device::new(
|
||||
@ -1652,7 +1649,7 @@ impl Renderer {
|
||||
|
||||
device.end_frame();
|
||||
|
||||
let backend_notifier = Arc::clone(¬ifier);
|
||||
let backend_notifier = notifier.clone();
|
||||
|
||||
let default_font_render_mode = match (options.enable_aa, options.enable_subpixel_aa) {
|
||||
(true, true) => FontRenderMode::Subpixel,
|
||||
@ -1735,7 +1732,6 @@ impl Renderer {
|
||||
ps_split_composite,
|
||||
ps_composite,
|
||||
ps_line,
|
||||
notifier,
|
||||
debug: debug_renderer,
|
||||
debug_flags,
|
||||
enable_batcher: options.enable_batcher,
|
||||
@ -1794,15 +1790,6 @@ impl Renderer {
|
||||
(color_space as usize)
|
||||
}
|
||||
|
||||
/// Sets the new RenderNotifier.
|
||||
///
|
||||
/// The RenderNotifier will be called when processing e.g. of a (scrolling) frame is done,
|
||||
/// and therefore the screen should be updated.
|
||||
pub fn set_render_notifier(&self, notifier: Box<RenderNotifier>) {
|
||||
let mut notifier_arc = self.notifier.lock().unwrap();
|
||||
*notifier_arc = Some(notifier);
|
||||
}
|
||||
|
||||
/// Returns the Epoch of the current frame in a pipeline.
|
||||
pub fn current_epoch(&self, pipeline_id: PipelineId) -> Option<Epoch> {
|
||||
self.pipeline_epoch_map.get(&pipeline_id).cloned()
|
||||
@ -2890,6 +2877,7 @@ impl Renderer {
|
||||
target: &AlphaRenderTarget,
|
||||
target_size: DeviceUintSize,
|
||||
projection: &Transform3D<f32>,
|
||||
render_tasks: &RenderTaskTree,
|
||||
) {
|
||||
self.gpu_profile.add_sampler(GPU_SAMPLER_TAG_ALPHA);
|
||||
|
||||
@ -2908,6 +2896,14 @@ impl Renderer {
|
||||
let clear_color = [1.0, 1.0, 1.0, 0.0];
|
||||
self.device
|
||||
.clear_target_rect(Some(clear_color), None, target.used_rect());
|
||||
|
||||
let zero_color = [0.0, 0.0, 0.0, 0.0];
|
||||
for task_id in &target.zero_clears {
|
||||
let task = render_tasks.get(*task_id);
|
||||
let (rect, _) = task.get_target_rect();
|
||||
self.device
|
||||
.clear_target_rect(Some(zero_color), None, rect);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw any blurs for this target.
|
||||
@ -3238,6 +3234,7 @@ impl Renderer {
|
||||
target,
|
||||
pass.max_alpha_target_size,
|
||||
&projection,
|
||||
&frame.render_tasks,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -430,7 +430,7 @@ impl ResourceCache {
|
||||
self.blob_image_renderer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.update(image_key, mem::replace(blob, BlobImageData::new()));
|
||||
.update(image_key, mem::replace(blob, BlobImageData::new()), dirty_rect);
|
||||
}
|
||||
|
||||
ImageResource {
|
||||
|
@ -21,7 +21,7 @@ use prim_store::{DeferredResolve, TextRunMode};
|
||||
use profiler::FrameProfileCounters;
|
||||
use render_task::{AlphaRenderItem, ClipWorkItem, MaskGeometryKind, MaskSegment};
|
||||
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKey, RenderTaskKind};
|
||||
use render_task::{RenderTaskLocation, RenderTaskTree};
|
||||
use render_task::{BlurTask, ClearMode, RenderTaskLocation, RenderTaskTree};
|
||||
use renderer::BlendMode;
|
||||
use renderer::ImageBufferKind;
|
||||
use resource_cache::{GlyphFetchResult, ResourceCache};
|
||||
@ -427,6 +427,7 @@ impl AlphaRenderItem {
|
||||
{
|
||||
let sub_index = i as i32;
|
||||
match *instance_kind {
|
||||
BorderCornerInstance::None => {}
|
||||
BorderCornerInstance::Single => {
|
||||
batch.push(base_instance.build(
|
||||
sub_index,
|
||||
@ -580,7 +581,7 @@ impl AlphaRenderItem {
|
||||
let textures = BatchTextures::render_target_cache();
|
||||
let kind = BatchKind::Transformable(
|
||||
transform_kind,
|
||||
TransformBatchKind::CacheImage(picture.kind),
|
||||
TransformBatchKind::CacheImage(picture.target_kind()),
|
||||
);
|
||||
let key = BatchKey::new(kind, blend_mode, textures);
|
||||
let batch = batch_list.get_suitable_batch(key, item_bounding_rect);
|
||||
@ -1137,23 +1138,23 @@ impl RenderTarget for ColorRenderTarget {
|
||||
});
|
||||
}
|
||||
}
|
||||
RenderTaskKind::VerticalBlur(..) => {
|
||||
// Find the child render task that we are applying
|
||||
// a vertical blur on.
|
||||
self.vertical_blurs.push(BlurInstance {
|
||||
task_address: render_tasks.get_task_address(task_id),
|
||||
src_task_address: render_tasks.get_task_address(task.children[0]),
|
||||
blur_direction: BlurDirection::Vertical,
|
||||
});
|
||||
RenderTaskKind::VerticalBlur(ref info) => {
|
||||
info.add_instances(
|
||||
&mut self.vertical_blurs,
|
||||
task_id,
|
||||
task.children[0],
|
||||
BlurDirection::Vertical,
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::HorizontalBlur(..) => {
|
||||
// Find the child render task that we are applying
|
||||
// a horizontal blur on.
|
||||
self.horizontal_blurs.push(BlurInstance {
|
||||
task_address: render_tasks.get_task_address(task_id),
|
||||
src_task_address: render_tasks.get_task_address(task.children[0]),
|
||||
blur_direction: BlurDirection::Horizontal,
|
||||
});
|
||||
RenderTaskKind::HorizontalBlur(ref info) => {
|
||||
info.add_instances(
|
||||
&mut self.horizontal_blurs,
|
||||
task_id,
|
||||
task.children[0],
|
||||
BlurDirection::Horizontal,
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::Picture(ref task_info) => {
|
||||
let prim_metadata = ctx.prim_store.get_metadata(task_info.prim_index);
|
||||
@ -1244,6 +1245,7 @@ pub struct AlphaRenderTarget {
|
||||
// List of blur operations to apply for this render target.
|
||||
pub vertical_blurs: Vec<BlurInstance>,
|
||||
pub horizontal_blurs: Vec<BlurInstance>,
|
||||
pub zero_clears: Vec<RenderTaskId>,
|
||||
allocator: TextureAllocator,
|
||||
}
|
||||
|
||||
@ -1258,6 +1260,7 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
rect_cache_prims: Vec::new(),
|
||||
vertical_blurs: Vec::new(),
|
||||
horizontal_blurs: Vec::new(),
|
||||
zero_clears: Vec::new(),
|
||||
allocator: TextureAllocator::new(size.expect("bug: alpha targets need size")),
|
||||
}
|
||||
}
|
||||
@ -1275,6 +1278,17 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
clip_store: &ClipStore,
|
||||
) {
|
||||
let task = render_tasks.get(task_id);
|
||||
|
||||
match task.clear_mode {
|
||||
ClearMode::Zero => {
|
||||
self.zero_clears.push(task_id);
|
||||
}
|
||||
ClearMode::One => {}
|
||||
ClearMode::Transparent => {
|
||||
panic!("bug: invalid clear mode for alpha task");
|
||||
}
|
||||
}
|
||||
|
||||
match task.kind {
|
||||
RenderTaskKind::Alias(..) => {
|
||||
panic!("BUG: add_task() called on invalidated task");
|
||||
@ -1283,23 +1297,23 @@ impl RenderTarget for AlphaRenderTarget {
|
||||
RenderTaskKind::Readback(..) => {
|
||||
panic!("Should not be added to alpha target!");
|
||||
}
|
||||
RenderTaskKind::VerticalBlur(..) => {
|
||||
// Find the child render task that we are applying
|
||||
// a vertical blur on.
|
||||
self.vertical_blurs.push(BlurInstance {
|
||||
task_address: render_tasks.get_task_address(task_id),
|
||||
src_task_address: render_tasks.get_task_address(task.children[0]),
|
||||
blur_direction: BlurDirection::Vertical,
|
||||
});
|
||||
RenderTaskKind::VerticalBlur(ref info) => {
|
||||
info.add_instances(
|
||||
&mut self.vertical_blurs,
|
||||
task_id,
|
||||
task.children[0],
|
||||
BlurDirection::Vertical,
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::HorizontalBlur(..) => {
|
||||
// Find the child render task that we are applying
|
||||
// a horizontal blur on.
|
||||
self.horizontal_blurs.push(BlurInstance {
|
||||
task_address: render_tasks.get_task_address(task_id),
|
||||
src_task_address: render_tasks.get_task_address(task.children[0]),
|
||||
blur_direction: BlurDirection::Horizontal,
|
||||
});
|
||||
RenderTaskKind::HorizontalBlur(ref info) => {
|
||||
info.add_instances(
|
||||
&mut self.horizontal_blurs,
|
||||
task_id,
|
||||
task.children[0],
|
||||
BlurDirection::Horizontal,
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::Picture(ref task_info) => {
|
||||
let prim_metadata = ctx.prim_store.get_metadata(task_info.prim_index);
|
||||
@ -1873,3 +1887,32 @@ fn resolve_image(
|
||||
None => (SourceTexture::Invalid, GpuCacheHandle::new()),
|
||||
}
|
||||
}
|
||||
|
||||
impl BlurTask {
|
||||
fn add_instances(
|
||||
&self,
|
||||
instances: &mut Vec<BlurInstance>,
|
||||
task_id: RenderTaskId,
|
||||
source_task_id: RenderTaskId,
|
||||
blur_direction: BlurDirection,
|
||||
render_tasks: &RenderTaskTree,
|
||||
) {
|
||||
let instance = BlurInstance {
|
||||
task_address: render_tasks.get_task_address(task_id),
|
||||
src_task_address: render_tasks.get_task_address(source_task_id),
|
||||
blur_direction,
|
||||
region: LayerRect::zero(),
|
||||
};
|
||||
|
||||
if self.regions.is_empty() {
|
||||
instances.push(instance);
|
||||
} else {
|
||||
for region in &self.regions {
|
||||
instances.push(BlurInstance {
|
||||
region: *region,
|
||||
..instance
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "webrender_api"
|
||||
version = "0.52.1"
|
||||
version = "0.53.0"
|
||||
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/servo/webrender"
|
||||
@ -15,7 +15,6 @@ bitflags = "1.0"
|
||||
bincode = "0.9"
|
||||
byteorder = "1.0"
|
||||
euclid = "0.15"
|
||||
heapsize = ">= 0.3.6, < 0.5"
|
||||
ipc-channel = {version = "0.9", optional = true}
|
||||
serde = { version = "1.0", features = ["rc", "derive"] }
|
||||
time = "0.1"
|
||||
|
@ -873,10 +873,11 @@ pub struct DynamicProperties {
|
||||
}
|
||||
|
||||
pub trait RenderNotifier: Send {
|
||||
fn new_frame_ready(&mut self);
|
||||
fn new_scroll_frame_ready(&mut self, composite_needed: bool);
|
||||
fn external_event(&mut self, _evt: ExternalEvent) {
|
||||
fn clone(&self) -> Box<RenderNotifier>;
|
||||
fn new_frame_ready(&self);
|
||||
fn new_scroll_frame_ready(&self, composite_needed: bool);
|
||||
fn external_event(&self, _evt: ExternalEvent) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn shut_down(&mut self) {}
|
||||
fn shut_down(&self) {}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ pub struct ColorF {
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
known_heap_size!(0, ColorF);
|
||||
|
||||
impl ColorF {
|
||||
/// Constructs a new `ColorF` from its components.
|
||||
|
@ -6,6 +6,7 @@ use {ColorF, FontInstanceKey, ImageKey, LayerPixel, LayoutPixel, LayoutPoint, La
|
||||
LayoutSize, LayoutTransform};
|
||||
use {GlyphOptions, LayoutVector2D, PipelineId, PropertyBinding};
|
||||
use euclid::{SideOffsets2D, TypedRect, TypedSideOffsets2D};
|
||||
use std::ops::Not;
|
||||
|
||||
// NOTE: some of these structs have an "IMPLICIT" comment.
|
||||
// This indicates that the BuiltDisplayList will have serialized
|
||||
@ -297,7 +298,7 @@ pub struct BoxShadowDisplayItem {
|
||||
pub color: ColorF,
|
||||
pub blur_radius: f32,
|
||||
pub spread_radius: f32,
|
||||
pub border_radius: f32,
|
||||
pub border_radius: BorderRadius,
|
||||
pub clip_mode: BoxShadowClipMode,
|
||||
}
|
||||
|
||||
@ -336,7 +337,6 @@ pub struct GradientStop {
|
||||
pub offset: f32,
|
||||
pub color: ColorF,
|
||||
}
|
||||
known_heap_size!(0, GradientStop);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RadialGradient {
|
||||
@ -376,8 +376,6 @@ pub enum ScrollPolicy {
|
||||
Fixed = 1,
|
||||
}
|
||||
|
||||
known_heap_size!(0, ScrollPolicy);
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum TransformStyle {
|
||||
@ -547,12 +545,31 @@ impl LocalClip {
|
||||
ComplexClipRegion {
|
||||
rect: complex.rect.translate(offset),
|
||||
radii: complex.radii,
|
||||
mode: complex.mode,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ClipMode {
|
||||
Clip, // Pixels inside the region are visible.
|
||||
ClipOut, // Pixels outside the region are visible.
|
||||
}
|
||||
|
||||
impl Not for ClipMode {
|
||||
type Output = ClipMode;
|
||||
|
||||
fn not(self) -> ClipMode {
|
||||
match self {
|
||||
ClipMode::Clip => ClipMode::ClipOut,
|
||||
ClipMode::ClipOut => ClipMode::Clip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ComplexClipRegion {
|
||||
@ -560,6 +577,9 @@ pub struct ComplexClipRegion {
|
||||
pub rect: LayoutRect,
|
||||
/// Border radii of this rectangle.
|
||||
pub radii: BorderRadius,
|
||||
/// Whether we are clipping inside or outside
|
||||
/// the region.
|
||||
pub mode: ClipMode,
|
||||
}
|
||||
|
||||
impl BorderRadius {
|
||||
@ -619,8 +639,12 @@ impl BorderRadius {
|
||||
|
||||
impl ComplexClipRegion {
|
||||
/// Create a new complex clip region.
|
||||
pub fn new(rect: LayoutRect, radii: BorderRadius) -> ComplexClipRegion {
|
||||
ComplexClipRegion { rect, radii }
|
||||
pub fn new(
|
||||
rect: LayoutRect,
|
||||
radii: BorderRadius,
|
||||
mode: ClipMode,
|
||||
) -> ComplexClipRegion {
|
||||
ComplexClipRegion { rect, radii, mode }
|
||||
}
|
||||
}
|
||||
|
||||
@ -672,21 +696,3 @@ impl ClipId {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_empty_heap_size_of {
|
||||
($name:ident) => {
|
||||
impl ::heapsize::HeapSizeOf for $name {
|
||||
fn heap_size_of_children(&self) -> usize { 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define_empty_heap_size_of!(ClipAndScrollInfo);
|
||||
define_empty_heap_size_of!(ClipId);
|
||||
define_empty_heap_size_of!(ImageKey);
|
||||
define_empty_heap_size_of!(LocalClip);
|
||||
define_empty_heap_size_of!(MixBlendMode);
|
||||
define_empty_heap_size_of!(RepeatMode);
|
||||
define_empty_heap_size_of!(ScrollSensitivity);
|
||||
define_empty_heap_size_of!(StickySideConstraint);
|
||||
define_empty_heap_size_of!(TransformStyle);
|
||||
|
@ -12,7 +12,7 @@ use {LineDisplayItem, LineOrientation, LineStyle, LocalClip, MixBlendMode, Pipel
|
||||
use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
|
||||
use {RectangleDisplayItem, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity};
|
||||
use {SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, StickyFrameInfo};
|
||||
use {TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
|
||||
use {BorderRadius, TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
|
||||
use YuvImageDisplayItem;
|
||||
use bincode;
|
||||
use serde::{Deserialize, Serialize, Serializer};
|
||||
@ -153,23 +153,25 @@ fn skip_slice<T: for<'de> Deserialize<'de>>(
|
||||
data: &mut &[u8],
|
||||
) -> (ItemRange<T>, usize) {
|
||||
let base = list.data.as_ptr() as usize;
|
||||
let start = data.as_ptr() as usize;
|
||||
|
||||
// Read through the values (this is a bit of a hack to reuse logic)
|
||||
let mut iter = AuxIter::<T>::new(*data);
|
||||
let count = iter.len();
|
||||
for _ in &mut iter {}
|
||||
let end = iter.data.as_ptr() as usize;
|
||||
let byte_size: usize = bincode::deserialize_from(data, bincode::Infinite)
|
||||
.expect("MEH: malicious input?");
|
||||
let start = data.as_ptr() as usize;
|
||||
let item_count: usize = bincode::deserialize_from(data, bincode::Infinite)
|
||||
.expect("MEH: malicious input?");
|
||||
|
||||
// Remember how many bytes item_count occupied
|
||||
let item_count_size = data.as_ptr() as usize - start;
|
||||
|
||||
let range = ItemRange {
|
||||
start: start - base,
|
||||
length: end - start,
|
||||
start: start - base, // byte offset to item_count
|
||||
length: byte_size + item_count_size, // number of bytes for item_count + payload
|
||||
_boo: PhantomData,
|
||||
};
|
||||
|
||||
// Adjust data pointer to skip read values
|
||||
*data = &data[range.length ..];
|
||||
(range, count)
|
||||
*data = &data[byte_size ..];
|
||||
(range, item_count)
|
||||
}
|
||||
|
||||
|
||||
@ -737,12 +739,29 @@ impl DisplayListBuilder {
|
||||
let len = iter.len();
|
||||
let mut count = 0;
|
||||
|
||||
// Format:
|
||||
// payload_byte_size: usize, item_count: usize, [I; item_count]
|
||||
|
||||
// We write a dummy value so there's room for later
|
||||
let byte_size_offset = self.data.len();
|
||||
serialize_fast(&mut self.data, &0usize);
|
||||
serialize_fast(&mut self.data, &len);
|
||||
let payload_offset = self.data.len();
|
||||
|
||||
for elem in iter {
|
||||
count += 1;
|
||||
serialize_fast(&mut self.data, &elem);
|
||||
}
|
||||
|
||||
// Now write the actual byte_size
|
||||
let final_offset = self.data.len();
|
||||
let byte_size = final_offset - payload_offset;
|
||||
|
||||
// Note we don't use serialize_fast because we don't want to change the Vec's len
|
||||
bincode::serialize_into(&mut &mut self.data[byte_size_offset..],
|
||||
&byte_size,
|
||||
bincode::Infinite).unwrap();
|
||||
|
||||
debug_assert_eq!(len, count);
|
||||
}
|
||||
|
||||
@ -1024,7 +1043,7 @@ impl DisplayListBuilder {
|
||||
color: ColorF,
|
||||
blur_radius: f32,
|
||||
spread_radius: f32,
|
||||
border_radius: f32,
|
||||
border_radius: BorderRadius,
|
||||
clip_mode: BoxShadowClipMode,
|
||||
) {
|
||||
let item = SpecificDisplayItem::BoxShadow(BoxShadowDisplayItem {
|
||||
|
@ -151,7 +151,7 @@ pub trait BlobImageResources {
|
||||
pub trait BlobImageRenderer: Send {
|
||||
fn add(&mut self, key: ImageKey, data: BlobImageData, tiling: Option<TileSize>);
|
||||
|
||||
fn update(&mut self, key: ImageKey, data: BlobImageData);
|
||||
fn update(&mut self, key: ImageKey, data: BlobImageData, dirty_rect: Option<DeviceUintRect>);
|
||||
|
||||
fn delete(&mut self, key: ImageKey);
|
||||
|
||||
|
@ -13,8 +13,6 @@ extern crate byteorder;
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate core;
|
||||
extern crate euclid;
|
||||
#[macro_use]
|
||||
extern crate heapsize;
|
||||
#[cfg(feature = "ipc")]
|
||||
extern crate ipc_channel;
|
||||
#[macro_use]
|
||||
|
@ -5,7 +5,7 @@ authors = ["The Mozilla Project Developers"]
|
||||
license = "MPL-2.0"
|
||||
|
||||
[dependencies]
|
||||
webrender_api = {path = "../webrender_api", version = "0.52.1"}
|
||||
webrender_api = {path = "../webrender_api", version = "0.53.0"}
|
||||
bincode = "0.8"
|
||||
rayon = "0.8"
|
||||
thread_profiler = "0.1.1"
|
||||
@ -15,5 +15,5 @@ gleam = "0.4"
|
||||
|
||||
[dependencies.webrender]
|
||||
path = "../webrender"
|
||||
version = "0.52.1"
|
||||
version = "0.53.0"
|
||||
default-features = false
|
||||
|
Loading…
x
Reference in New Issue
Block a user