Skip to content

Commit

Permalink
Auto merge of #1807 - glennw:canvas1, r=nical
Browse files Browse the repository at this point in the history
Add canvas as a more general version of the shadow primitive.

This doesn't add any functional changes, but it lays the foundation
for moving box shadows and other render task operations over to
unified as canvas primitives.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1807)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo authored Oct 5, 2017
2 parents 29d325f + 84b0bd1 commit cb06be0
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 144 deletions.
66 changes: 34 additions & 32 deletions webrender/src/frame_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ use euclid::{SideOffsets2D, vec2, vec3};
use frame::FrameId;
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, FastHashSet, HardwareCompositeOp};
use picture::PicturePrimitive;
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{BoxShadowPrimitiveCpu, TexelRect, YuvImagePrimitiveCpu};
use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu, LinePrimitive, PrimitiveKind};
use prim_store::{PrimitiveContainer, PrimitiveIndex};
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu};
use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu, ShadowPrimitiveCpu};
use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_task::{AlphaRenderItem, ClipWorkItem, RenderTask};
use render_task::{RenderTaskId, RenderTaskLocation, RenderTaskTree};
Expand Down Expand Up @@ -584,11 +585,7 @@ impl FrameBuilder {
clip_and_scroll: ClipAndScrollInfo,
info: &LayerPrimitiveInfo,
) {
let prim = ShadowPrimitiveCpu {
shadow,
primitives: Vec::new(),
render_task_id: None,
};
let prim = PicturePrimitive::new_shadow(shadow);

// Create an empty shadow primitive. Insert it into
// the draw lists immediately so that it will be drawn
Expand All @@ -598,7 +595,7 @@ impl FrameBuilder {
clip_and_scroll,
info,
Vec::new(),
PrimitiveContainer::Shadow(prim),
PrimitiveContainer::Picture(prim),
);

self.shadow_prim_stack.push(prim_index);
Expand All @@ -614,9 +611,10 @@ impl FrameBuilder {
// safe to offset the local rect by the offset of the shadow, which
// 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_shadows[metadata.cpu_prim_index.0];
let prim = &self.prim_store.cpu_pictures[metadata.cpu_prim_index.0];
let shadow = prim.as_shadow();

metadata.local_rect = metadata.local_rect.translate(&prim.shadow.offset);
metadata.local_rect = metadata.local_rect.translate(&shadow.offset);
}

pub fn add_solid_rectangle(
Expand Down Expand Up @@ -686,9 +684,10 @@ impl FrameBuilder {
let mut fast_shadow_prims = Vec::new();
for shadow_prim_index in &self.shadow_prim_stack {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let shadow_prim = &self.prim_store.cpu_shadows[shadow_metadata.cpu_prim_index.0];
if shadow_prim.shadow.blur_radius == 0.0 {
fast_shadow_prims.push(shadow_prim.shadow);
let picture = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let shadow = picture.as_shadow();
if shadow.blur_radius == 0.0 {
fast_shadow_prims.push(shadow.clone());
}
}
for shadow in fast_shadow_prims {
Expand Down Expand Up @@ -720,18 +719,19 @@ impl FrameBuilder {

for shadow_prim_index in &self.shadow_prim_stack {
let shadow_metadata = &mut self.prim_store.cpu_metadata[shadow_prim_index.0];
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Shadow);
let shadow_prim =
&mut self.prim_store.cpu_shadows[shadow_metadata.cpu_prim_index.0];
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;

// Only run real blurs here (fast path zero blurs are handled above).
if shadow_prim.shadow.blur_radius > 0.0 {
if blur_radius > 0.0 {
let shadow_rect = new_rect.inflate(
shadow_prim.shadow.blur_radius,
shadow_prim.shadow.blur_radius,
blur_radius,
blur_radius,
);
shadow_metadata.local_rect = shadow_metadata.local_rect.union(&shadow_rect);
shadow_prim.primitives.push(prim_index);
picture.add_primitive(prim_index, clip_and_scroll);
}
}
}
Expand Down Expand Up @@ -1211,20 +1211,21 @@ impl FrameBuilder {
let mut fast_shadow_prims = Vec::new();
for shadow_prim_index in &self.shadow_prim_stack {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let shadow_prim = &self.prim_store.cpu_shadows[shadow_metadata.cpu_prim_index.0];
if shadow_prim.shadow.blur_radius == 0.0 {
let picture_prim = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let shadow = picture_prim.as_shadow();
if shadow.blur_radius == 0.0 {
let mut text_prim = prim.clone();
if font.render_mode != FontRenderMode::Bitmap {
text_prim.font.color = shadow_prim.shadow.color.into();
text_prim.font.color = shadow.color.into();
}
// If we have translucent text, we need to ensure it won't go
// through the subpixel blend mode, which doesn't work with
// traditional alpha blending.
if shadow_prim.shadow.color.a != 1.0 {
if shadow.color.a != 1.0 {
text_prim.font.render_mode = text_prim.font.render_mode.limit_by(FontRenderMode::Alpha);
}
text_prim.color = shadow_prim.shadow.color;
text_prim.offset += shadow_prim.shadow.offset;
text_prim.color = shadow.color;
text_prim.offset += shadow.offset;
fast_shadow_prims.push(text_prim);
}
}
Expand Down Expand Up @@ -1264,18 +1265,19 @@ impl FrameBuilder {
// the indices as sub-primitives to the shadow primitives.
for shadow_prim_index in &self.shadow_prim_stack {
let shadow_metadata = &mut self.prim_store.cpu_metadata[shadow_prim_index.0];
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Shadow);
let shadow_prim =
&mut self.prim_store.cpu_shadows[shadow_metadata.cpu_prim_index.0];
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Picture);
let picture_prim =
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];

// Only run real blurs here (fast path zero blurs are handled above).
if shadow_prim.shadow.blur_radius > 0.0 {
let blur_radius = picture_prim.as_shadow().blur_radius;
if blur_radius > 0.0 {
let shadow_rect = rect.inflate(
shadow_prim.shadow.blur_radius,
shadow_prim.shadow.blur_radius,
blur_radius,
blur_radius,
);
shadow_metadata.local_rect = shadow_metadata.local_rect.union(&shadow_rect);
shadow_prim.primitives.push(prim_index);
picture_prim.add_primitive(prim_index, clip_and_scroll);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions webrender/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ mod glyph_rasterizer;
mod gpu_cache;
mod gpu_types;
mod internal_types;
mod picture;
mod prim_store;
mod print_tree;
mod profiler;
Expand Down
79 changes: 79 additions & 0 deletions webrender/src/picture.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* 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/. */

use api::{ClipAndScrollInfo, Shadow};
use prim_store::PrimitiveIndex;
use render_task::RenderTaskId;

/*
A picture represents a dynamically rendered image. It consists of:
* A number of primitives that are drawn onto the picture.
* A composite operation describing how to composite this
picture into its parent.
* A configuration describing how to draw the primitives on
this picture (e.g. in screen space or local space).
*/

#[derive(Clone, Debug)]
pub struct PrimitiveRun {
pub prim_index: PrimitiveIndex,
pub count: usize,
pub clip_and_scroll: ClipAndScrollInfo,
}

#[derive(Debug)]
pub enum CompositeOp {
Shadow(Shadow),

// TODO(gw): Support other composite ops, such
// as blur, blend etc.
}

#[derive(Debug)]
pub struct PicturePrimitive {
pub prim_runs: Vec<PrimitiveRun>,
pub composite_op: CompositeOp,
pub render_task_id: Option<RenderTaskId>,

// TODO(gw): Add a mode that specifies if this
// picture should be rasterized in
// screen-space or local-space.
}

impl PicturePrimitive {
pub fn new_shadow(shadow: Shadow) -> PicturePrimitive {
PicturePrimitive {
prim_runs: Vec::new(),
composite_op: CompositeOp::Shadow(shadow),
render_task_id: None,
}
}

pub fn as_shadow(&self) -> &Shadow {
match self.composite_op {
CompositeOp::Shadow(ref shadow) => shadow,
}
}

pub fn add_primitive(
&mut self,
prim_index: PrimitiveIndex,
clip_and_scroll: ClipAndScrollInfo
) {
if let Some(ref mut run) = self.prim_runs.last_mut() {
if run.clip_and_scroll == clip_and_scroll &&
run.prim_index.0 + run.count == prim_index.0 {
run.count += 1;
return;
}
}

self.prim_runs.push(PrimitiveRun {
prim_index,
count: 1,
clip_and_scroll,
});
}
}
Loading

0 comments on commit cb06be0

Please sign in to comment.