Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the per-item complex clipping and masking from the API #1412

Merged
merged 1 commit into from Jun 23, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Remove the per-item complex clipping and masking from the API

This is the first step to getting all masking operations into the
ClipScrollTree. We don't completely this feature, as it's still sued
for the extra clips. These will be moved into the ClipScrollTree in a
later change. This change allows us to fully eliminate the
DisplayListBuilder::push_clip_region API and push its functionality
into the define_clip API.

Most of the changes here are:
  1. Changes to the examples, wrench, and reftests to match the new API.
  2. Adapting the "split rectangle clipped by rounded rect"
     optimization to use the ClipScrollTree. This is unfortunately a
     bit more complicated now, but now includes any rounded rect clip
     instead of per-item ones.
  • Loading branch information
mrobinson committed Jun 23, 2017
commit 0bf665541573a7ec845ba702c2ae6d208a789ce8
@@ -23,8 +23,7 @@ use webrender_traits::*;
fn body(_api: &RenderApi,
builder: &mut DisplayListBuilder,
_pipeline_id: &PipelineId,
_layout_size: &LayoutSize)
{
_layout_size: &LayoutSize) {
// Create a 100x100 stacking context with an animatable transform property.
// Note the magic "42" we use as the animation key. That is used to update
// the transform in the keyboard event handler code.
@@ -38,9 +37,8 @@ fn body(_api: &RenderApi,
Vec::new());

// Fill it with a white rect
let clip = builder.push_clip_region(&bounds, vec![], None);
builder.push_rect(bounds,
clip,
bounds,
ColorF::new(1.0, 1.0, 1.0, 1.0));

builder.pop_stacking_context();
@@ -9,19 +9,21 @@ extern crate glutin;
extern crate webrender;
extern crate webrender_traits;

#[macro_use]
extern crate lazy_static;

#[path="common/boilerplate.rs"]
mod boilerplate;

use app_units::Au;
use gleam::gl;
use boilerplate::HandyDandyRectBuilder;
use euclid::vec2;
use glutin::TouchPhase;
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use webrender_traits::{ClipRegionToken, ColorF, DisplayListBuilder, Epoch, GlyphInstance};
use webrender_traits::{DeviceIntPoint, DeviceUintSize, LayoutPoint, LayoutRect, LayoutSize};
use webrender_traits::{ImageData, ImageDescriptor, ImageFormat};
use webrender_traits::{PipelineId, RenderApi, TransformStyle, BoxShadowClipMode};
use euclid::vec2;
use std::sync::Mutex;
use webrender_traits::*;

#[derive(Debug)]
enum Gesture {
@@ -168,143 +170,64 @@ fn load_file(name: &str) -> Vec<u8> {
buffer
}

struct Notifier {
window_proxy: glutin::WindowProxy,
}

impl Notifier {
fn new(window_proxy: glutin::WindowProxy) -> Notifier {
Notifier {
window_proxy,
}
}
fn main() {
boilerplate::main_wrapper(body, event_handler, None);
}

impl webrender_traits::RenderNotifier for Notifier {
fn new_frame_ready(&mut self) {
#[cfg(not(target_os = "android"))]
self.window_proxy.wakeup_event_loop();
}

fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {
#[cfg(not(target_os = "android"))]
self.window_proxy.wakeup_event_loop();
}
}
fn body(api: &RenderApi,
builder: &mut DisplayListBuilder,
_pipeline_id: &PipelineId,
layout_size: &LayoutSize) {
let bounds = LayoutRect::new(LayoutPoint::zero(), *layout_size);
builder.push_stacking_context(ScrollPolicy::Scrollable,
bounds,
None,
TransformStyle::Flat,
None,
MixBlendMode::Normal,
Vec::new());

fn push_sub_clip(api: &RenderApi, builder: &mut DisplayListBuilder, bounds: &LayoutRect)
-> ClipRegionToken {
let mask_image = api.generate_image_key();
api.add_image(mask_image,
let image_mask_key = api.generate_image_key();
api.add_image(image_mask_key,
ImageDescriptor::new(2, 2, ImageFormat::A8, true),
ImageData::new(vec![0, 80, 180, 255]),
None);
let mask = webrender_traits::ImageMask {
image: mask_image,
rect: LayoutRect::new(LayoutPoint::new(75.0, 75.0), LayoutSize::new(100.0, 100.0)),
let mask = ImageMask {
image: image_mask_key,
rect: (75, 75).by(100, 100),
repeat: false,
};
let complex = webrender_traits::ComplexClipRegion::new(
LayoutRect::new(LayoutPoint::new(50.0, 50.0), LayoutSize::new(100.0, 100.0)),
webrender_traits::BorderRadius::uniform(20.0));

builder.push_clip_region(bounds, vec![complex], Some(mask))
}


fn main() {
let args: Vec<String> = env::args().collect();
let res_path = if args.len() > 1 {
Some(PathBuf::from(&args[1]))
} else {
None
};

let window = glutin::WindowBuilder::new()
.with_title("WebRender Sample")
.with_multitouch()
.with_gl(glutin::GlRequest::GlThenGles {
opengl_version: (3, 2),
opengles_version: (3, 0)
})
.build()
.unwrap();

unsafe {
window.make_current().ok();
}

let gl = match gl::GlType::default() {
gl::GlType::Gl => unsafe { gl::GlFns::load_with(|symbol| window.get_proc_address(symbol) as *const _) },
gl::GlType::Gles => unsafe { gl::GlesFns::load_with(|symbol| window.get_proc_address(symbol) as *const _) },
};
let complex = ComplexClipRegion::new((50, 50).to(150, 150), BorderRadius::uniform(20.0));
builder.push_clip_node(None, bounds, bounds, vec![complex], Some(mask));

println!("OpenGL version {}", gl.get_string(gl::VERSION));
println!("Shader resource path: {:?}", res_path);
let bounds = (100, 100).to(200, 200);
builder.push_rect(bounds, bounds, ColorF::new(0.0, 1.0, 0.0, 1.0));

let (width, height) = window.get_inner_size_pixels().unwrap();

let opts = webrender::RendererOptions {
resource_override_path: res_path,
debug: true,
precache_shaders: true,
device_pixel_ratio: window.hidpi_factor(),
.. Default::default()
};

let size = DeviceUintSize::new(width, height);
let (mut renderer, sender) = webrender::renderer::Renderer::new(gl, opts, size).unwrap();
let api = sender.create_api();

let notifier = Box::new(Notifier::new(window.create_window_proxy()));
renderer.set_render_notifier(notifier);

let epoch = Epoch(0);
let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);

let pipeline_id = PipelineId(0, 0);
let layout_size = LayoutSize::new(width as f32, height as f32);
let mut builder = webrender_traits::DisplayListBuilder::new(pipeline_id, layout_size);

let bounds = LayoutRect::new(LayoutPoint::zero(), layout_size);
builder.push_stacking_context(webrender_traits::ScrollPolicy::Scrollable,
bounds,
None,
TransformStyle::Flat,
None,
webrender_traits::MixBlendMode::Normal,
Vec::new());

let clip = push_sub_clip(&api, &mut builder, &bounds);
builder.push_rect(LayoutRect::new(LayoutPoint::new(100.0, 100.0), LayoutSize::new(100.0, 100.0)),
clip,
let bounds = (250, 100).to(350, 200);
builder.push_rect(bounds,
bounds,
ColorF::new(0.0, 1.0, 0.0, 1.0));

let clip = push_sub_clip(&api, &mut builder, &bounds);
builder.push_rect(LayoutRect::new(LayoutPoint::new(250.0, 100.0), LayoutSize::new(100.0, 100.0)),
clip,
ColorF::new(0.0, 1.0, 0.0, 1.0));
let border_side = webrender_traits::BorderSide {
let border_side = BorderSide {
color: ColorF::new(0.0, 0.0, 1.0, 1.0),
style: webrender_traits::BorderStyle::Groove,
style: BorderStyle::Groove,
};
let border_widths = webrender_traits::BorderWidths {
let border_widths = BorderWidths {
top: 10.0,
left: 10.0,
bottom: 10.0,
right: 10.0,
};
let border_details = webrender_traits::BorderDetails::Normal(webrender_traits::NormalBorder {
let border_details = BorderDetails::Normal(NormalBorder {
top: border_side,
right: border_side,
bottom: border_side,
left: border_side,
radius: webrender_traits::BorderRadius::uniform(20.0),
radius: BorderRadius::uniform(20.0),
});

let clip = push_sub_clip(&api, &mut builder, &bounds);
builder.push_border(LayoutRect::new(LayoutPoint::new(100.0, 100.0), LayoutSize::new(100.0, 100.0)),
clip,
let bounds = (100, 100).to(200, 200);
builder.push_border(bounds,
bounds,
border_widths,
border_details);

@@ -314,8 +237,7 @@ fn main() {
let font_bytes = load_file("res/FreeSans.ttf");
api.add_raw_font(font_key, font_bytes, 0);

let text_bounds = LayoutRect::new(LayoutPoint::new(100.0, 200.0), LayoutSize::new(700.0, 300.0));

let text_bounds = (100, 200).by(700, 300);
let glyphs = vec![
GlyphInstance {
index: 48,
@@ -367,9 +289,8 @@ fn main() {
},
];

let clip = builder.push_clip_region(&bounds, Vec::new(), None);
builder.push_text(text_bounds,
clip,
text_bounds,
&glyphs,
font_key,
ColorF::new(1.0, 1.0, 0.0, 1.0),
@@ -379,19 +300,17 @@ fn main() {
}

if false { // draw box shadow?
let rect = LayoutRect::new(LayoutPoint::new(0.0, 0.0), LayoutSize::new(0.0, 0.0));
let simple_box_bounds = LayoutRect::new(LayoutPoint::new(20.0, 200.0),
LayoutSize::new(50.0, 50.0));
let rect = LayoutRect::zero();
let simple_box_bounds = (20, 200).by(50, 50);
let offset = vec2(10.0, 10.0);
let color = ColorF::new(1.0, 1.0, 1.0, 1.0);
let blur_radius = 0.0;
let spread_radius = 0.0;
let simple_border_radius = 8.0;
let box_shadow_type = BoxShadowClipMode::Inset;
let full_screen_clip = builder.push_clip_region(&bounds, Vec::new(), None);

builder.push_box_shadow(rect,
full_screen_clip,
bounds,
simple_box_bounds,
offset,
color,
@@ -401,57 +320,29 @@ fn main() {
box_shadow_type);
}

builder.pop_clip_node();
builder.pop_stacking_context();
}

api.set_display_list(
Some(root_background_color),
epoch,
LayoutSize::new(width as f32, height as f32),
builder.finalize(),
true);
api.set_root_pipeline(pipeline_id);
api.generate_frame(None);

let mut touch_state = TouchState::new();

'outer: for event in window.wait_events() {
let mut events = Vec::new();
events.push(event);

for event in window.poll_events() {
events.push(event);
}
lazy_static! {
static ref TOUCH_STATE: Mutex<TouchState> = Mutex::new(TouchState::new());
}

for event in events {
match event {
glutin::Event::Closed |
glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Q)) => break 'outer,
glutin::Event::KeyboardInput(glutin::ElementState::Pressed,
_, Some(glutin::VirtualKeyCode::P)) => {
let enable_profiler = !renderer.get_profiler_enabled();
renderer.set_profiler_enabled(enable_profiler);
fn event_handler(event: &glutin::Event, api: &RenderApi) {
match *event {
glutin::Event::Touch(touch) => {
match TOUCH_STATE.lock().unwrap().handle_event(touch) {
TouchResult::Pan(pan) => {
api.set_pan(pan);
api.generate_frame(None);
}
glutin::Event::Touch(touch) => {
match touch_state.handle_event(touch) {
TouchResult::Pan(pan) => {
api.set_pan(pan);
api.generate_frame(None);
}
TouchResult::Zoom(zoom) => {
api.set_pinch_zoom(webrender_traits::ZoomFactor::new(zoom));
api.generate_frame(None);
}
TouchResult::None => {}
}
TouchResult::Zoom(zoom) => {
api.set_pinch_zoom(ZoomFactor::new(zoom));
api.generate_frame(None);
}
_ => ()
TouchResult::None => {}
}
}

renderer.update();
renderer.render(DeviceUintSize::new(width, height));
window.swap_buffers().ok();
_ => ()
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.