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

Picture caching support, part 1 (of 2). #3332

Merged
merged 10 commits into from Nov 23, 2018
@@ -24,58 +24,59 @@ use euclid::Angle;
use webrender::api::*;

struct App {
property_key: PropertyBindingKey<LayoutTransform>,
property_key0: PropertyBindingKey<LayoutTransform>,
property_key1: PropertyBindingKey<LayoutTransform>,
property_key2: PropertyBindingKey<LayoutTransform>,
opacity_key: PropertyBindingKey<f32>,
transform: LayoutTransform,
opacity: f32,
angle0: f32,
angle1: f32,
angle2: f32,
}

impl Example for App {
fn render(
impl App {
fn add_rounded_rect(
&mut self,
_api: &RenderApi,
bounds: LayoutRect,
color: ColorF,
builder: &mut DisplayListBuilder,
_txn: &mut Transaction,
_framebuffer_size: DeviceIntSize,
_pipeline_id: PipelineId,
_document_id: DocumentId,
property_key: PropertyBindingKey<LayoutTransform>,
) {
// Create a 200x200 stacking context with an animated transform property.
let bounds = (0, 0).to(200, 200);

let filters = [
FilterOp::Opacity(PropertyBinding::Binding(self.opacity_key, self.opacity), self.opacity),
];

let info = LayoutPrimitiveInfo::new(bounds);
let reference_frame_id = builder.push_reference_frame(
&info,
Some(PropertyBinding::Binding(self.property_key, LayoutTransform::identity())),
&LayoutPrimitiveInfo::new(LayoutRect::new(bounds.origin, LayoutSize::zero())),
Some(PropertyBinding::Binding(property_key, LayoutTransform::identity())),
None,
);

builder.push_clip_id(reference_frame_id);

let info = LayoutPrimitiveInfo::new(bounds);
builder.push_stacking_context(
&info,
&LayoutPrimitiveInfo::new(LayoutRect::zero()),
None,
TransformStyle::Flat,
MixBlendMode::Normal,
&filters,
RasterSpace::Screen,
);

let clip_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
let complex_clip = ComplexClipRegion {
rect: bounds,
radii: BorderRadius::uniform(50.0),
rect: clip_bounds,
radii: BorderRadius::uniform(30.0),
mode: ClipMode::Clip,
};
let clip_id = builder.define_clip(bounds, vec![complex_clip], None);
let clip_id = builder.define_clip(clip_bounds, vec![complex_clip], None);
builder.push_clip_id(clip_id);

// Fill it with a white rect
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
builder.push_rect(
&LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(), bounds.size)),
color,
);

builder.pop_clip_id();

@@ -84,6 +85,33 @@ impl Example for App {
builder.pop_clip_id();
builder.pop_reference_frame();
}
}

impl Example for App {
const WIDTH: u32 = 1024;
const HEIGHT: u32 = 1024;

fn render(
&mut self,
_api: &RenderApi,
builder: &mut DisplayListBuilder,
_txn: &mut Transaction,
_framebuffer_size: DeviceIntSize,
_pipeline_id: PipelineId,
_document_id: DocumentId,
) {
let bounds = (150, 150).to(250, 250);
let key0 = self.property_key0;
self.add_rounded_rect(bounds, ColorF::new(1.0, 0.0, 0.0, 0.5), builder, key0);

let bounds = (400, 400).to(600, 600);
let key1 = self.property_key1;
self.add_rounded_rect(bounds, ColorF::new(0.0, 1.0, 0.0, 0.5), builder, key1);

let bounds = (200, 500).to(350, 580);
let key2 = self.property_key2;
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, key2);
}

fn on_event(&mut self, win_event: winit::WindowEvent, api: &RenderApi, document_id: DocumentId) -> bool {
match win_event {
@@ -95,31 +123,38 @@ impl Example for App {
},
..
} => {
let (offset_x, offset_y, angle, delta_opacity) = match key {
winit::VirtualKeyCode::Down => (0.0, 10.0, 0.0, 0.0),
winit::VirtualKeyCode::Up => (0.0, -10.0, 0.0, 0.0),
winit::VirtualKeyCode::Right => (10.0, 0.0, 0.0, 0.0),
winit::VirtualKeyCode::Left => (-10.0, 0.0, 0.0, 0.0),
winit::VirtualKeyCode::Comma => (0.0, 0.0, 0.1, 0.0),
winit::VirtualKeyCode::Period => (0.0, 0.0, -0.1, 0.0),
winit::VirtualKeyCode::Z => (0.0, 0.0, 0.0, -0.1),
winit::VirtualKeyCode::X => (0.0, 0.0, 0.0, 0.1),
let (delta_angle, delta_opacity) = match key {
winit::VirtualKeyCode::Down => (0.0, -0.1),
winit::VirtualKeyCode::Up => (0.0, 0.1),
winit::VirtualKeyCode::Right => (1.0, 0.0),
winit::VirtualKeyCode::Left => (-1.0, 0.0),
_ => return false,
};
// Update the transform based on the keyboard input and push it to
// webrender using the generate_frame API. This will recomposite with
// the updated transform.
self.opacity += delta_opacity;
let new_transform = self.transform
.pre_rotate(0.0, 0.0, 1.0, Angle::radians(angle))
.post_translate(LayoutVector3D::new(offset_x, offset_y, 0.0));
self.angle0 += delta_angle * 0.1;
self.angle1 += delta_angle * 0.2;
self.angle2 -= delta_angle * 0.15;
let xf0 = LayoutTransform::create_rotation(0.0, 0.0, 1.0, Angle::radians(self.angle0));
let xf1 = LayoutTransform::create_rotation(0.0, 0.0, 1.0, Angle::radians(self.angle1));
let xf2 = LayoutTransform::create_rotation(0.0, 0.0, 1.0, Angle::radians(self.angle2));
let mut txn = Transaction::new();
txn.update_dynamic_properties(
DynamicProperties {
transforms: vec![
PropertyValue {
key: self.property_key,
value: new_transform,
key: self.property_key0,
value: xf0,
},
PropertyValue {
key: self.property_key1,
value: xf1,
},
PropertyValue {
key: self.property_key2,
value: xf2,
},
],
floats: vec![
@@ -132,7 +167,6 @@ impl Example for App {
);
txn.generate_frame();
api.send_transaction(document_id, txn);
self.transform = new_transform;
}
_ => (),
}
@@ -143,10 +177,14 @@ impl Example for App {

fn main() {
let mut app = App {
property_key: PropertyBindingKey::new(42), // arbitrary magic number
property_key0: PropertyBindingKey::new(42), // arbitrary magic number
property_key1: PropertyBindingKey::new(44), // arbitrary magic number
property_key2: PropertyBindingKey::new(45), // arbitrary magic number
opacity_key: PropertyBindingKey::new(43),
transform: LayoutTransform::create_translation(0.0, 0.0, 0.0),
opacity: 0.5,
angle0: 0.0,
angle1: 0.0,
angle2: 0.0,
};
boilerplate::main_wrapper(&mut app, None);
}
@@ -179,6 +179,8 @@ pub fn main_wrapper<E: Example>(
renderer.set_external_image_handler(external_image_handler);
}

renderer.toggle_debug_flags(webrender::DebugFlags::TEXTURE_CACHE_DBG);

let epoch = Epoch(0);
let pipeline_id = PipelineId(0, 0);
let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
@@ -195,7 +197,7 @@ pub fn main_wrapper<E: Example>(
);
txn.set_display_list(
epoch,
None,
Some(ColorF::new(0.3, 0.0, 0.0, 1.0)),
layout_size,
builder.finalize(),
true,
@@ -293,7 +295,7 @@ pub fn main_wrapper<E: Example>(
);
txn.set_display_list(
epoch,
None,
Some(ColorF::new(0.3, 0.0, 0.0, 1.0)),
layout_size,
builder.finalize(),
true,
@@ -24,6 +24,8 @@ void brush_vs(
#define BRUSH_FLAG_SEGMENT_REPEAT_Y 8
#define BRUSH_FLAG_TEXEL_RECT 16

#define INVALID_SEGMENT_INDEX 0xffff

void main(void) {
// Load the brush instance from vertex attributes.
int prim_header_address = aData.x;
@@ -35,12 +37,20 @@ void main(void) {
PrimitiveHeader ph = fetch_prim_header(prim_header_address);

// Fetch the segment of this brush primitive we are drawing.
int segment_address = ph.specific_prim_address +
VECS_PER_SPECIFIC_BRUSH +
segment_index * VECS_PER_SEGMENT;
vec4 segment_data;
RectWithSize segment_rect;
if (segment_index == INVALID_SEGMENT_INDEX) {
segment_rect = ph.local_rect;
segment_data = vec4(0.0);
} else {
int segment_address = ph.specific_prim_address +
VECS_PER_SPECIFIC_BRUSH +
segment_index * VECS_PER_SEGMENT;

vec4[2] segment_data = fetch_from_gpu_cache_2(segment_address);
RectWithSize local_segment_rect = RectWithSize(segment_data[0].xy, segment_data[0].zw);
vec4[2] segment_info = fetch_from_gpu_cache_2(segment_address);
segment_rect = RectWithSize(segment_info[0].xy, segment_info[0].zw);
segment_data = segment_info[1];
}

VertexInfo vi;

@@ -53,7 +63,7 @@ void main(void) {
// Write the normal vertex information out.
if (transform.is_axis_aligned) {
vi = write_vertex(
local_segment_rect,
segment_rect,
ph.local_clip_rect,
ph.z,
transform,
@@ -74,7 +84,7 @@ void main(void) {
bvec4 edge_mask = notEqual(edge_flags & ivec4(1, 2, 4, 8), ivec4(0));

vi = write_transform_vertex(
local_segment_rect,
segment_rect,
ph.local_rect,
ph.local_clip_rect,
mix(vec4(0.0), vec4(1.0), edge_mask),
@@ -103,12 +113,12 @@ void main(void) {
vi,
ph.specific_prim_address,
ph.local_rect,
local_segment_rect,
segment_rect,
ivec4(ph.user_data, segment_user_data),
transform.m,
pic_task,
brush_flags,
segment_data[1]
segment_data
);
}
#endif
@@ -73,6 +73,9 @@ void brush_vs(

RectWithSize local_rect = prim_rect;
vec2 stretch_size = image_data.stretch_size;
if (stretch_size.x < 0.0) {
stretch_size = local_rect.size;
}

// If this segment should interpolate relative to the
// segment, modify the parameters for that.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.