Bug 1496171. Update webrender to commit 3c3f9a4e919b81639f078d7bd101012de61b9396

This commit is contained in:
Jeff Muizelaar 2018-10-04 23:16:32 -04:00
Родитель 1e79f89539
Коммит 1ddc54bd0f
31 изменённых файлов: 592 добавлений и 395 удалений

Просмотреть файл

@ -42,20 +42,6 @@ ImageBrushData fetch_image_data(int address) {
return data;
}
#ifdef WR_FEATURE_ALPHA_PASS
vec2 transform_point_snapped(
vec2 local_pos,
RectWithSize local_rect,
mat4 transform
) {
vec2 snap_offset = compute_snap_offset(local_pos, transform, local_rect);
vec4 world_pos = transform * vec4(local_pos, 0.0, 1.0);
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
return device_pos + snap_offset;
}
#endif
void brush_vs(
VertexInfo vi,
int prim_address,
@ -95,10 +81,10 @@ void brush_vs(
// works. That assumption may not hold if this
// is used for other purposes in the future.
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
stretch_size.x = (texel_rect.z - texel_rect.x) / uDevicePixelRatio;
stretch_size.x = (texel_rect.z - texel_rect.x) / pic_task.common_data.device_pixel_scale;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
stretch_size.y = (texel_rect.w - texel_rect.y) / uDevicePixelRatio;
stretch_size.y = (texel_rect.w - texel_rect.y) / pic_task.common_data.device_pixel_scale;
}
uv0 = res.uv_rect.p0 + texel_rect.xy;

Просмотреть файл

@ -12,6 +12,11 @@ flat varying int vOp;
#ifdef WR_VERTEX_SHADER
//Note: this function is unsafe for `vi.world_pos.w <= 0.0`
vec2 snap_device_pos(VertexInfo vi, float device_pixel_scale) {
return vi.world_pos.xy * device_pixel_scale / max(0.0, vi.world_pos.w) + vi.snap_offset;
}
void brush_vs(
VertexInfo vi,
int prim_address,
@ -23,7 +28,7 @@ void brush_vs(
int brush_flags,
vec4 unused
) {
vec2 snapped_device_pos = snap_device_pos(vi);
vec2 snapped_device_pos = snap_device_pos(vi, pic_task.common_data.device_pixel_scale);
vec2 texture_size = vec2(textureSize(sPrevPassColor, 0));
vOp = user_data.x;

Просмотреть файл

@ -63,7 +63,8 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
mat4 snap_mat = clip_transform.m * prim_transform.inv_m;
vec4 snap_positions = compute_snap_positions(
snap_mat,
local_clip_rect
local_clip_rect,
area.common_data.device_pixel_scale
);
vec2 snap_offsets = compute_snap_offset_impl(
@ -77,7 +78,7 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
device_pos -= snap_offsets;
}
vec2 world_pos = device_pos / uDevicePixelRatio;
vec2 world_pos = device_pos / area.common_data.device_pixel_scale;
vec4 pos = prim_transform.m * vec4(world_pos, 0.0, 1.0);
pos.xyz /= pos.w;

Просмотреть файл

@ -32,7 +32,7 @@ BlurTask fetch_blur_task(int address) {
BlurTask task = BlurTask(
task_data.common_data,
task_data.data1.x
task_data.user_data.x
);
return task;

Просмотреть файл

@ -12,7 +12,7 @@ in vec4 aColor;
void main(void) {
vColor = vec4(aColor.rgb * aColor.a, aColor.a);
vec4 pos = vec4(aPosition, 1.0);
pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio;
pos.xy = floor(pos.xy + 0.5);
gl_Position = uTransform * pos;
}
#endif

Просмотреть файл

@ -15,7 +15,7 @@ void main(void) {
vColor = aColor;
vColorTexCoord = aColorTexCoord;
vec4 pos = vec4(aPosition, 1.0);
pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio;
pos.xy = floor(pos.xy + 0.5);
gl_Position = uTransform * pos;
}
#endif

Просмотреть файл

@ -89,11 +89,6 @@ struct VertexInfo {
vec4 world_pos;
};
//Note: this function is unsafe for `vi.world_pos.w <= 0.0`
vec2 snap_device_pos(VertexInfo vi) {
return vi.world_pos.xy * uDevicePixelRatio / max(0.0, vi.world_pos.w) + vi.snap_offset;
}
VertexInfo write_vertex(RectWithSize instance_rect,
RectWithSize local_clip_rect,
float z,
@ -111,14 +106,15 @@ VertexInfo write_vertex(RectWithSize instance_rect,
vec2 snap_offset = compute_snap_offset(
clamped_local_pos,
transform.m,
snap_rect
snap_rect,
task.common_data.device_pixel_scale
);
// Transform the current vertex to world space.
vec4 world_pos = transform.m * vec4(clamped_local_pos, 0.0, 1.0);
// Convert the world positions to device pixel space.
vec2 device_pos = world_pos.xy * uDevicePixelRatio;
vec2 device_pos = world_pos.xy * task.common_data.device_pixel_scale;
// Apply offsets for the render task to get correct screen location.
vec2 final_offset = snap_offset - task.content_origin + task.common_data.task_rect.p0;
@ -195,7 +191,7 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
// Transform the current vertex to the world cpace.
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
vec4 final_pos = vec4(
world_pos.xy * uDevicePixelRatio + task_offset * world_pos.w,
world_pos.xy * task.common_data.device_pixel_scale + task_offset * world_pos.w,
z * world_pos.w,
world_pos.w
);
@ -218,7 +214,7 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
}
void write_clip(vec4 world_pos, vec2 snap_offset, ClipArea area) {
vec2 uv = world_pos.xy * uDevicePixelRatio +
vec2 uv = world_pos.xy * area.common_data.device_pixel_scale +
world_pos.w * (snap_offset + area.common_data.task_rect.p0 - area.screen_origin);
vClipMaskUvBounds = vec4(
area.common_data.task_rect.p0,

Просмотреть файл

@ -73,7 +73,7 @@ void main(void) {
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
vec4 final_pos = vec4(
dest_origin * world_pos.w + world_pos.xy * uDevicePixelRatio,
dest_origin * world_pos.w + world_pos.xy * dest_task.common_data.device_pixel_scale,
world_pos.w * ci.z,
world_pos.w
);

Просмотреть файл

@ -81,7 +81,7 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
// Compute the snapping offset only if the scroll node transform is axis-aligned.
if (remove_subpx_offset) {
// Transform from local space to device space.
float device_scale = uDevicePixelRatio / transform.m[3].w;
float device_scale = task.common_data.device_pixel_scale / transform.m[3].w;
mat2 device_transform = mat2(transform.m) * device_scale;
// Ensure the transformed text offset does not contain a subpixel translation
@ -130,7 +130,7 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
// Map the clamped local space corner into device space.
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
vec2 device_pos = world_pos.xy / world_pos.w * task.common_data.device_pixel_scale;
// Apply offsets for the render task to get correct screen location.
vec2 final_pos = device_pos -
@ -172,7 +172,7 @@ void main(void) {
#ifdef WR_FEATURE_GLYPH_TRANSFORM
// Transform from local space to glyph space.
mat2 glyph_transform = mat2(transform.m) * uDevicePixelRatio;
mat2 glyph_transform = mat2(transform.m) * task.common_data.device_pixel_scale;
// Compute the glyph rect in glyph space.
RectWithSize glyph_rect = RectWithSize(res.offset + glyph_transform * (text.offset + glyph.offset),
@ -180,7 +180,7 @@ void main(void) {
#else
// Scale from glyph space to local space.
float scale = res.scale / uDevicePixelRatio;
float scale = res.scale / task.common_data.device_pixel_scale;
// Compute the glyph rect in local space.
RectWithSize glyph_rect = RectWithSize(scale * res.offset + text.offset + glyph.offset,

Просмотреть файл

@ -11,11 +11,12 @@ uniform HIGHP_SAMPLER_FLOAT sampler2D sRenderTasks;
struct RenderTaskCommonData {
RectWithSize task_rect;
float texture_layer_index;
float device_pixel_scale;
};
struct RenderTaskData {
RenderTaskCommonData common_data;
vec3 data1;
vec2 user_data;
};
RenderTaskData fetch_render_task_data(int index) {
@ -31,12 +32,13 @@ RenderTaskData fetch_render_task_data(int index) {
RenderTaskCommonData common_data = RenderTaskCommonData(
task_rect,
texel1.x
texel1.x,
texel1.y
);
RenderTaskData data = RenderTaskData(
common_data,
texel1.yzw
texel1.zw
);
return data;
@ -55,7 +57,8 @@ RenderTaskCommonData fetch_render_task_common_data(int index) {
RenderTaskCommonData data = RenderTaskCommonData(
task_rect,
texel1.x
texel1.x,
texel1.y
);
return data;
@ -79,7 +82,7 @@ PictureTask fetch_picture_task(int address) {
PictureTask task = PictureTask(
task_data.common_data,
task_data.data1.xy
task_data.user_data
);
return task;
@ -90,7 +93,6 @@ PictureTask fetch_picture_task(int address) {
struct ClipArea {
RenderTaskCommonData common_data;
vec2 screen_origin;
bool local_space;
};
ClipArea fetch_clip_area(int index) {
@ -99,15 +101,13 @@ ClipArea fetch_clip_area(int index) {
if (index >= CLIP_TASK_EMPTY) {
RectWithSize rect = RectWithSize(vec2(0.0), vec2(0.0));
area.common_data = RenderTaskCommonData(rect, 0.0);
area.common_data = RenderTaskCommonData(rect, 0.0, 1.0);
area.screen_origin = vec2(0.0);
area.local_space = false;
} else {
RenderTaskData task_data = fetch_render_task_data(index);
area.common_data = task_data.common_data;
area.screen_origin = task_data.data1.xy;
area.local_space = task_data.data1.z == 0.0;
area.screen_origin = task_data.user_data;
}
return area;

Просмотреть файл

@ -30,7 +30,6 @@
// Uniform inputs
uniform mat4 uTransform; // Orthographic projection
uniform float uDevicePixelRatio;
// Attribute inputs
in vec3 aPosition;

Просмотреть файл

@ -4,21 +4,25 @@
#ifdef WR_VERTEX_SHADER
vec4 compute_snap_positions(mat4 transform, RectWithSize snap_rect) {
vec4 compute_snap_positions(
mat4 transform,
RectWithSize snap_rect,
float device_pixel_scale
) {
// Ensure that the snap rect is at *least* one device pixel in size.
// TODO(gw): It's not clear to me that this is "correct". Specifically,
// how should it interact with sub-pixel snap rects when there
// is a transform with scale present? But it does fix
// the test cases we have in Servo that are failing without it
// and seem better than not having this at all.
snap_rect.size = max(snap_rect.size, vec2(1.0 / uDevicePixelRatio));
snap_rect.size = max(snap_rect.size, vec2(1.0 / device_pixel_scale));
// Transform the snap corners to the world space.
vec4 world_snap_p0 = transform * vec4(snap_rect.p0, 0.0, 1.0);
vec4 world_snap_p1 = transform * vec4(snap_rect.p0 + snap_rect.size, 0.0, 1.0);
// Snap bounds in world coordinates, adjusted for pixel ratio. XY = top left, ZW = bottom right
vec4 world_snap = uDevicePixelRatio * vec4(world_snap_p0.xy, world_snap_p1.xy) /
vec4(world_snap_p0.ww, world_snap_p1.ww);
vec4 world_snap = device_pixel_scale * vec4(world_snap_p0.xy, world_snap_p1.xy) /
vec4(world_snap_p0.ww, world_snap_p1.ww);
return world_snap;
}
@ -43,10 +47,12 @@ vec2 compute_snap_offset_impl(
// given local position on the transform and a snap rectangle.
vec2 compute_snap_offset(vec2 local_pos,
mat4 transform,
RectWithSize snap_rect) {
RectWithSize snap_rect,
float device_pixel_scale) {
vec4 snap_positions = compute_snap_positions(
transform,
snap_rect
snap_rect,
device_pixel_scale
);
vec2 snap_offsets = compute_snap_offset_impl(

Просмотреть файл

@ -1229,11 +1229,9 @@ fn add_clip_node_to_current_chain(
let conversion = if spatial_node_index == clip_spatial_node_index {
Some(ClipSpaceConversion::Local)
} else if ref_spatial_node.coordinate_system_id == clip_spatial_node.coordinate_system_id {
let scale_offset = ref_spatial_node
.coordinate_system_relative_scale_offset
.difference(
&clip_spatial_node.coordinate_system_relative_scale_offset
);
let scale_offset = ref_spatial_node.coordinate_system_relative_scale_offset
.inverse()
.accumulate(&clip_spatial_node.coordinate_system_relative_scale_offset);
Some(ClipSpaceConversion::ScaleOffset(scale_offset))
} else {
let xf = clip_scroll_tree.get_relative_transform(

Просмотреть файл

@ -105,10 +105,19 @@ pub struct DebugRenderer {
impl DebugRenderer {
pub fn new(device: &mut Device) -> Result<Self, ShaderError> {
let font_program = device.create_program("debug_font", "", &DESC_FONT)?;
let font_program = device.create_program_linked(
"debug_font",
"",
&DESC_FONT,
)?;
device.bind_program(&font_program);
device.bind_shader_samplers(&font_program, &[("sColor0", DebugSampler::Font)]);
let color_program = device.create_program("debug_color", "", &DESC_COLOR)?;
let color_program = device.create_program_linked(
"debug_color",
"",
&DESC_COLOR,
)?;
let font_vao = device.create_vao(&DESC_FONT);
let line_vao = device.create_vao(&DESC_COLOR);

Просмотреть файл

@ -526,11 +526,24 @@ impl Drop for Texture {
}
}
/// Temporary state retained by a program when it
/// is created, discarded when it is linked.
struct ProgramInitState {
base_filename: String,
sources: ProgramSources,
}
pub struct Program {
id: gl::GLuint,
u_transform: gl::GLint,
u_device_pixel_ratio: gl::GLint,
u_mode: gl::GLint,
init_state: Option<ProgramInitState>,
}
impl Program {
pub fn is_initialized(&self) -> bool {
self.init_state.is_none()
}
}
impl Drop for Program {
@ -1036,8 +1049,132 @@ impl Device {
}
}
/// Link a program, attaching the supplied vertex format.
/// Ideally, this should be run some time after the program
/// is created. This gives some drivers time to compile the
/// shader on a background thread, before blocking due to
/// an API call accessing the shader.
pub fn link_program(
&mut self,
program: &mut Program,
descriptor: &VertexDescriptor,
) -> Result<(), ShaderError> {
if let Some(init_state) = program.init_state.take() {
let mut build_program = true;
// See if we hit the binary shader cache
if let Some(ref cached_programs) = self.cached_programs {
if let Some(binary) = cached_programs.binaries.borrow().get(&init_state.sources) {
let mut link_status = [0];
unsafe {
self.gl.get_program_iv(program.id, gl::LINK_STATUS, &mut link_status);
}
if link_status[0] == 0 {
let error_log = self.gl.get_program_info_log(program.id);
error!(
"Failed to load a program object with a program binary: {} renderer {}\n{}",
&init_state.base_filename,
self.renderer_name,
error_log
);
if let Some(ref program_cache_handler) = cached_programs.program_cache_handler {
program_cache_handler.notify_program_binary_failed(&binary);
}
} else {
build_program = false;
}
}
}
// If not, we need to do a normal compile + link pass.
if build_program {
// Compile the vertex shader
let vs_id =
match Device::compile_shader(&*self.gl, &init_state.base_filename, gl::VERTEX_SHADER, &init_state.sources.vs_source) {
Ok(vs_id) => vs_id,
Err(err) => return Err(err),
};
// Compile the fragment shader
let fs_id =
match Device::compile_shader(&*self.gl, &init_state.base_filename, gl::FRAGMENT_SHADER, &init_state.sources.fs_source) {
Ok(fs_id) => fs_id,
Err(err) => {
self.gl.delete_shader(vs_id);
return Err(err);
}
};
// Attach shaders
self.gl.attach_shader(program.id, vs_id);
self.gl.attach_shader(program.id, fs_id);
// Bind vertex attributes
for (i, attr) in descriptor
.vertex_attributes
.iter()
.chain(descriptor.instance_attributes.iter())
.enumerate()
{
self.gl
.bind_attrib_location(program.id, i as gl::GLuint, attr.name);
}
if self.cached_programs.is_some() {
self.gl.program_parameter_i(program.id, gl::PROGRAM_BINARY_RETRIEVABLE_HINT, gl::TRUE as gl::GLint);
}
// Link!
self.gl.link_program(program.id);
// GL recommends detaching and deleting shaders once the link
// is complete (whether successful or not). This allows the driver
// to free any memory associated with the parsing and compilation.
self.gl.detach_shader(program.id, vs_id);
self.gl.detach_shader(program.id, fs_id);
self.gl.delete_shader(vs_id);
self.gl.delete_shader(fs_id);
let mut link_status = [0];
unsafe {
self.gl.get_program_iv(program.id, gl::LINK_STATUS, &mut link_status);
}
if link_status[0] == 0 {
let error_log = self.gl.get_program_info_log(program.id);
error!(
"Failed to link shader program: {}\n{}",
&init_state.base_filename,
error_log
);
self.gl.delete_program(program.id);
return Err(ShaderError::Link(init_state.base_filename.clone(), error_log));
}
if let Some(ref cached_programs) = self.cached_programs {
if !cached_programs.binaries.borrow().contains_key(&init_state.sources) {
let (buffer, format) = self.gl.get_program_binary(program.id);
if buffer.len() > 0 {
let program_binary = Arc::new(ProgramBinary::new(buffer, format, &init_state.sources));
if let Some(ref program_cache_handler) = cached_programs.program_cache_handler {
program_cache_handler.notify_binary_added(&program_binary);
}
cached_programs.binaries.borrow_mut().insert(init_state.sources, program_binary);
}
}
}
}
// If we get here, the link succeeded, so get the uniforms.
program.u_transform = self.gl.get_uniform_location(program.id, "uTransform");
program.u_mode = self.gl.get_uniform_location(program.id, "uMode");
}
Ok(())
}
pub fn bind_program(&mut self, program: &Program) {
debug_assert!(self.inside_frame);
debug_assert!(program.init_state.is_none());
if self.bound_program != program.id {
self.gl.use_program(program.id);
@ -1431,11 +1568,25 @@ impl Device {
program.id = 0;
}
pub fn create_program(
/// Create a shader program and link it immediately.
pub fn create_program_linked(
&mut self,
base_filename: &str,
features: &str,
descriptor: &VertexDescriptor,
) -> Result<Program, ShaderError> {
let mut program = self.create_program(base_filename, features)?;
self.link_program(&mut program, descriptor)?;
Ok(program)
}
/// Create a shader program. This does minimal amount of work
/// to start loading a binary shader. The main part of the
/// work is done in link_program.
pub fn create_program(
&mut self,
base_filename: &str,
features: &str,
) -> Result<Program, ShaderError> {
debug_assert!(self.inside_frame);
@ -1453,124 +1604,29 @@ impl Device {
// Create program
let pid = self.gl.create_program();
let mut loaded = false;
// Attempt to load a cached binary if possible.
if let Some(ref cached_programs) = self.cached_programs {
if let Some(binary) = cached_programs.binaries.borrow().get(&sources)
{
if let Some(binary) = cached_programs.binaries.borrow().get(&sources) {
self.gl.program_binary(pid, binary.format, &binary.binary);
let mut link_status = [0];
unsafe {
self.gl.get_program_iv(pid, gl::LINK_STATUS, &mut link_status);
}
if link_status[0] == 0 {
let error_log = self.gl.get_program_info_log(pid);
error!(
"Failed to load a program object with a program binary: {} renderer {}\n{}",
base_filename,
self.renderer_name,
error_log
);
if let Some(ref program_cache_handler) = cached_programs.program_cache_handler {
program_cache_handler.notify_program_binary_failed(&binary);
}
} else {
loaded = true;
}
}
}
if loaded == false {
// Compile the vertex shader
let vs_id =
match Device::compile_shader(&*self.gl, base_filename, gl::VERTEX_SHADER, &sources.vs_source) {
Ok(vs_id) => vs_id,
Err(err) => return Err(err),
};
// Compiler the fragment shader
let fs_id =
match Device::compile_shader(&*self.gl, base_filename, gl::FRAGMENT_SHADER, &sources.fs_source) {
Ok(fs_id) => fs_id,
Err(err) => {
self.gl.delete_shader(vs_id);
return Err(err);
}
};
// Attach shaders
self.gl.attach_shader(pid, vs_id);
self.gl.attach_shader(pid, fs_id);
// Bind vertex attributes
for (i, attr) in descriptor
.vertex_attributes
.iter()
.chain(descriptor.instance_attributes.iter())
.enumerate()
{
self.gl
.bind_attrib_location(pid, i as gl::GLuint, attr.name);
}
if self.cached_programs.is_some() {
self.gl.program_parameter_i(pid, gl::PROGRAM_BINARY_RETRIEVABLE_HINT, gl::TRUE as gl::GLint);
}
// Link!
self.gl.link_program(pid);
// GL recommends detaching and deleting shaders once the link
// is complete (whether successful or not). This allows the driver
// to free any memory associated with the parsing and compilation.
self.gl.detach_shader(pid, vs_id);
self.gl.detach_shader(pid, fs_id);
self.gl.delete_shader(vs_id);
self.gl.delete_shader(fs_id);
let mut link_status = [0];
unsafe {
self.gl.get_program_iv(pid, gl::LINK_STATUS, &mut link_status);
}
if link_status[0] == 0 {
let error_log = self.gl.get_program_info_log(pid);
error!(
"Failed to link shader program: {}\n{}",
base_filename,
error_log
);
self.gl.delete_program(pid);
return Err(ShaderError::Link(base_filename.to_string(), error_log));
}
}
if let Some(ref cached_programs) = self.cached_programs {
if !cached_programs.binaries.borrow().contains_key(&sources) {
let (buffer, format) = self.gl.get_program_binary(pid);
if buffer.len() > 0 {
let program_binary = Arc::new(ProgramBinary::new(buffer, format, &sources));
if let Some(ref program_cache_handler) = cached_programs.program_cache_handler {
program_cache_handler.notify_binary_added(&program_binary);
}
cached_programs.binaries.borrow_mut().insert(sources, program_binary);
}
}
}
// Set up the init state that will be used in link_program.
let init_state = Some(ProgramInitState {
base_filename: base_filename.to_owned(),
sources,
});
let u_transform = self.gl.get_uniform_location(pid, "uTransform");
let u_device_pixel_ratio = self.gl.get_uniform_location(pid, "uDevicePixelRatio");
let u_mode = self.gl.get_uniform_location(pid, "uMode");
let program = Program {
id: pid,
u_transform,
u_device_pixel_ratio,
u_mode,
init_state,
};
self.bind_program(&program);
Ok(program)
}
@ -1578,6 +1634,9 @@ impl Device {
where
S: Into<TextureSlot> + Copy,
{
// bind_program() must be called before calling bind_shader_samplers
assert_eq!(self.bound_program, program.id);
for binding in bindings {
let u_location = self.gl.get_uniform_location(program.id, binding.0);
if u_location != -1 {
@ -1601,8 +1660,6 @@ impl Device {
debug_assert!(self.inside_frame);
self.gl
.uniform_matrix_4fv(program.u_transform, false, &transform.to_row_major_array());
self.gl
.uniform_1f(program.u_device_pixel_ratio, self.device_pixel_ratio);
}
pub fn switch_mode(&self, mode: i32) {

Просмотреть файл

@ -399,7 +399,7 @@ impl FrameBuilder {
let gpu_cache_frame_id = gpu_cache.end_frame(gpu_cache_profile);
render_tasks.write_task_data();
render_tasks.write_task_data(device_pixel_scale);
resource_cache.end_frame();

Просмотреть файл

@ -13,7 +13,7 @@ use internal_types::RenderTargetInfo;
use pathfinder_gfx_utils::ShelfBinPacker;
use profiler::GpuProfileTag;
use renderer::{self, ImageBufferKind, Renderer, RendererError, RendererStats};
use renderer::{TextureSampler, VertexArrayKind};
use renderer::{TextureSampler, VertexArrayKind, ShaderPrecacheFlags};
use shade::{LazilyCompiledShader, ShaderKind};
use tiling::GlyphJob;
@ -42,7 +42,7 @@ pub struct GpuGlyphRenderer {
}
impl GpuGlyphRenderer {
pub fn new(device: &mut Device, prim_vao: &VAO, precache_shaders: bool)
pub fn new(device: &mut Device, prim_vao: &VAO, precache_flags: ShaderPrecacheFlags)
-> Result<GpuGlyphRenderer, RendererError> {
// Make sure the area LUT is uncompressed grayscale TGA, 8bpp.
debug_assert!(AREA_LUT_TGA_BYTES[2] == 3);
@ -74,14 +74,14 @@ impl GpuGlyphRenderer {
"pf_vector_stencil",
&[ImageBufferKind::Texture2D.get_feature_string()],
device,
precache_shaders)
precache_flags)
};
let vector_cover = try!{
LazilyCompiledShader::new(ShaderKind::VectorCover,
"pf_vector_cover",
&[ImageBufferKind::Texture2D.get_feature_string()],
device,
precache_shaders)
precache_flags)
};
Ok(GpuGlyphRenderer {

Просмотреть файл

@ -186,7 +186,7 @@ pub use frame_builder::ChasePrimitive;
pub use renderer::{AsyncPropertySampler, CpuProfile, DebugFlags, OutputImageHandler, RendererKind};
pub use renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource, GpuProfile};
pub use renderer::{GraphicsApi, GraphicsApiInfo, PipelineInfo, Renderer, RendererOptions};
pub use renderer::{RendererStats, SceneBuilderHooks, ThreadListener};
pub use renderer::{RendererStats, SceneBuilderHooks, ThreadListener, ShaderPrecacheFlags};
pub use renderer::MAX_VERTEX_TEXTURE_WIDTH;
pub use webrender_api as api;
pub use resource_cache::intersect_for_tile;

Просмотреть файл

@ -131,7 +131,8 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
} else if ref_spatial_node.coordinate_system_id == target_spatial_node.coordinate_system_id {
CoordinateSpaceMapping::ScaleOffset(
ref_spatial_node.coordinate_system_relative_scale_offset
.difference(
.inverse()
.accumulate(
&target_spatial_node.coordinate_system_relative_scale_offset
)
)
@ -519,6 +520,58 @@ impl BrushSegment {
brush_flags,
}
}
pub fn update_clip_task(
&mut self,
clip_chain: Option<&ClipChainInstance>,
prim_bounding_rect: WorldRect,
root_spatial_node_index: SpatialNodeIndex,
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
) {
match clip_chain {
Some(clip_chain) => {
if !clip_chain.needs_mask ||
(!self.may_need_clip_mask && !clip_chain.has_non_local_clips) {
self.clip_task_id = BrushSegmentTaskId::Opaque;
return;
}
let (device_rect, _, _) = match get_raster_rects(
clip_chain.pic_clip_rect,
&pic_state.map_pic_to_raster,
&pic_state.map_raster_to_world,
prim_bounding_rect,
frame_context.device_pixel_scale,
) {
Some(info) => info,
None => {
self.clip_task_id = BrushSegmentTaskId::Empty;
return;
}
};
let clip_task = RenderTask::new_mask(
device_rect.to_i32(),
clip_chain.clips_range,
root_spatial_node_index,
frame_state.clip_store,
frame_state.gpu_cache,
frame_state.resource_cache,
frame_state.render_tasks,
&mut frame_state.resources.clip_data_store,
);
let clip_task_id = frame_state.render_tasks.add(clip_task);
pic_state.tasks.push(clip_task_id);
self.clip_task_id = BrushSegmentTaskId::RenderTaskId(clip_task_id);
}
None => {
self.clip_task_id = BrushSegmentTaskId::Empty;
}
}
}
}
pub type BrushSegmentVec = SmallVec<[BrushSegment; 8]>;
@ -2235,68 +2288,50 @@ impl Primitive {
None => return false,
};
for segment in &mut segment_desc.segments {
// Build a clip chain for the smaller segment rect. This will
// often manage to eliminate most/all clips, and sometimes
// clip the segment completely.
let segment_clip_chain = frame_state
.clip_store
.build_clip_chain_instance(
self.metadata.clip_chain_id,
segment.local_rect,
self.metadata.local_clip_rect,
prim_context.spatial_node_index,
&pic_state.map_local_to_pic,
&pic_state.map_pic_to_world,
&frame_context.clip_scroll_tree,
frame_state.gpu_cache,
frame_state.resource_cache,
frame_context.device_pixel_scale,
&frame_context.world_rect,
clip_node_collector,
&mut frame_state.resources.clip_data_store,
);
match segment_clip_chain {
Some(segment_clip_chain) => {
if !segment_clip_chain.needs_mask ||
(!segment.may_need_clip_mask && !segment_clip_chain.has_non_local_clips) {
segment.clip_task_id = BrushSegmentTaskId::Opaque;
continue;
}
let (device_rect, _, _) = match get_raster_rects(
segment_clip_chain.pic_clip_rect,
&pic_state.map_pic_to_raster,
&pic_state.map_raster_to_world,
prim_bounding_rect,
frame_context.device_pixel_scale,
) {
Some(info) => info,
None => {
segment.clip_task_id = BrushSegmentTaskId::Empty;
continue;
}
};
let clip_task = RenderTask::new_mask(
device_rect.to_i32(),
segment_clip_chain.clips_range,
root_spatial_node_index,
frame_state.clip_store,
// If we only built 1 segment, there is no point in re-running
// the clip chain builder. Instead, just use the clip chain
// instance that was built for the main primitive. This is a
// significant optimization for the common case.
if segment_desc.segments.len() == 1 {
segment_desc.segments[0].update_clip_task(
Some(prim_clip_chain),
prim_bounding_rect,
root_spatial_node_index,
pic_state,
frame_context,
frame_state,
);
} else {
for segment in &mut segment_desc.segments {
// Build a clip chain for the smaller segment rect. This will
// often manage to eliminate most/all clips, and sometimes
// clip the segment completely.
let segment_clip_chain = frame_state
.clip_store
.build_clip_chain_instance(
self.metadata.clip_chain_id,
segment.local_rect,
self.metadata.local_clip_rect,
prim_context.spatial_node_index,
&pic_state.map_local_to_pic,
&pic_state.map_pic_to_world,
&frame_context.clip_scroll_tree,
frame_state.gpu_cache,
frame_state.resource_cache,
frame_state.render_tasks,
frame_context.device_pixel_scale,
&frame_context.world_rect,
clip_node_collector,
&mut frame_state.resources.clip_data_store,
);
let clip_task_id = frame_state.render_tasks.add(clip_task);
pic_state.tasks.push(clip_task_id);
segment.clip_task_id = BrushSegmentTaskId::RenderTaskId(clip_task_id);
}
None => {
segment.clip_task_id = BrushSegmentTaskId::Empty;
}
segment.update_clip_task(
segment_clip_chain.as_ref(),
prim_bounding_rect,
root_spatial_node_index,
pic_state,
frame_context,
frame_state,
);
}
}

Просмотреть файл

@ -2,7 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets, ImageDescriptor, ImageFormat};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets};
use api::{DevicePixelScale, ImageDescriptor, ImageFormat};
#[cfg(feature = "pathfinder")]
use api::FontRenderMode;
use border::BorderCacheKey;
@ -15,7 +16,7 @@ use euclid::{TypedPoint2D, TypedVector2D};
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
use glyph_rasterizer::GpuGlyphCacheKey;
use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
use gpu_types::{BorderInstance, ImageSource, RasterizationSpace, UvRectKind};
use gpu_types::{BorderInstance, ImageSource, UvRectKind};
use internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex};
#[cfg(feature = "pathfinder")]
use pathfinder_partitioner::mesh::Mesh;
@ -131,9 +132,9 @@ impl RenderTaskTree {
RenderTaskAddress(id.0)
}
pub fn write_task_data(&mut self) {
pub fn write_task_data(&mut self, device_pixel_scale: DevicePixelScale) {
for task in &self.tasks {
self.task_data.push(task.write_task_data());
self.task_data.push(task.write_task_data(device_pixel_scale));
}
}
@ -709,7 +710,7 @@ impl RenderTask {
// Write (up to) 8 floats of data specific to the type
// of render task that is provided to the GPU shaders
// via a vertex texture.
pub fn write_task_data(&self) -> RenderTaskData {
pub fn write_task_data(&self, device_pixel_scale: DevicePixelScale) -> RenderTaskData {
// NOTE: The ordering and layout of these structures are
// required to match both the GPU structures declared
// in prim_shared.glsl, and also the uses in submit_batch()
@ -724,21 +725,12 @@ impl RenderTask {
[
task.content_origin.x as f32,
task.content_origin.y as f32,
0.0,
]
}
RenderTaskKind::CacheMask(ref task) => {
[
task.actual_rect.origin.x as f32,
task.actual_rect.origin.y as f32,
RasterizationSpace::Screen as i32 as f32,
]
}
RenderTaskKind::ClipRegion(..) => {
[
0.0,
0.0,
RasterizationSpace::Local as i32 as f32,
]
}
RenderTaskKind::VerticalBlur(ref task) |
@ -746,17 +738,17 @@ impl RenderTask {
[
task.blur_std_deviation,
0.0,
0.0,
]
}
RenderTaskKind::Glyph(_) => {
[1.0, 0.0, 0.0]
[1.0, 0.0]
}
RenderTaskKind::ClipRegion(..) |
RenderTaskKind::Readback(..) |
RenderTaskKind::Scaling(..) |
RenderTaskKind::Border(..) |
RenderTaskKind::Blit(..) => {
[0.0; 3]
[0.0; 2]
}
};
@ -775,9 +767,9 @@ impl RenderTask {
target_rect.size.width as f32,
target_rect.size.height as f32,
target_index.0 as f32,
device_pixel_scale.0,
data[0],
data[1],
data[2],
]
}
}

Просмотреть файл

@ -708,7 +708,7 @@ pub struct GpuGlyphRenderer;
#[cfg(not(feature = "pathfinder"))]
impl GpuGlyphRenderer {
fn new(_: &mut Device, _: &VAO, _: bool) -> Result<GpuGlyphRenderer, RendererError> {
fn new(_: &mut Device, _: &VAO, _: ShaderPrecacheFlags) -> Result<GpuGlyphRenderer, RendererError> {
Ok(GpuGlyphRenderer)
}
}
@ -1024,8 +1024,11 @@ impl GpuCacheTexture {
let texture = device.create_texture(TextureTarget::Default, ImageFormat::RGBAF32);
let bus = if use_scatter {
let program = device
.create_program("gpu_cache_update", "", &desc::GPU_CACHE_UPDATE)?;
let program = device.create_program_linked(
"gpu_cache_update",
"",
&desc::GPU_CACHE_UPDATE,
)?;
let buf_position = device.create_vbo();
let buf_value = device.create_vbo();
//Note: the vertex attributes have to be supplied in the same order
@ -1714,7 +1717,7 @@ impl Renderer {
let gpu_glyph_renderer = try!(GpuGlyphRenderer::new(&mut device,
&prim_vao,
options.precache_shaders));
options.precache_flags));
let blur_vao = device.create_vao_with_new_instances(&desc::BLUR, &prim_vao);
let clip_vao = device.create_vao_with_new_instances(&desc::CLIP, &prim_vao);
@ -4425,13 +4428,28 @@ pub trait AsyncPropertySampler {
fn deregister(&self);
}
/// Flags that control how shaders are pre-cached, if at all.
bitflags! {
#[derive(Default)]
pub struct ShaderPrecacheFlags: u32 {
/// Needed for const initialization
const EMPTY = 0;
/// Only start async compile
const ASYNC_COMPILE = 1 << 2;
/// Do a full compile/link during startup
const FULL_COMPILE = 1 << 3;
}
}
pub struct RendererOptions {
pub device_pixel_ratio: f32,
pub resource_override_path: Option<PathBuf>,
pub enable_aa: bool,
pub enable_dithering: bool,
pub max_recorded_profiles: usize,
pub precache_shaders: bool,
pub precache_flags: ShaderPrecacheFlags,
pub renderer_kind: RendererKind,
pub enable_subpixel_aa: bool,
pub clear_color: Option<ColorF>,
@ -4464,7 +4482,7 @@ impl Default for RendererOptions {
enable_dithering: true,
debug_flags: DebugFlags::empty(),
max_recorded_profiles: 0,
precache_shaders: false,
precache_flags: ShaderPrecacheFlags::empty(),
renderer_kind: RendererKind::Native,
enable_subpixel_aa: false,
clear_color: Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),

Просмотреть файл

@ -1443,10 +1443,11 @@ impl ResourceCache {
.unwrap()
.prepare_resources(&self.resources, &self.missing_blob_images);
let is_low_priority = false;
let rasterized_blobs = self.blob_image_rasterizer
.as_mut()
.unwrap()
.rasterize(&self.missing_blob_images);
.rasterize(&self.missing_blob_images, is_low_priority);
self.add_rasterized_blob_images(rasterized_blobs);
@ -1884,7 +1885,7 @@ impl ResourceCache {
let blob_handler = self.blob_image_handler.as_mut().unwrap();
blob_handler.prepare_resources(&self.resources, blob_request_params);
let mut rasterizer = blob_handler.create_blob_rasterizer();
let (_, result) = rasterizer.rasterize(blob_request_params).pop().unwrap();
let (_, result) = rasterizer.rasterize(blob_request_params, false).pop().unwrap();
let result = result.expect("Blob rasterization failed");
assert_eq!(result.rasterized_rect.size, desc.size);

Просмотреть файл

@ -447,10 +447,11 @@ impl SceneBuilder {
}
}
let is_low_priority = false;
let blob_requests = replace(&mut txn.blob_requests, Vec::new());
let mut rasterized_blobs = txn.blob_rasterizer.as_mut().map_or(
Vec::new(),
|rasterizer| rasterizer.rasterize(&blob_requests),
|rasterizer| rasterizer.rasterize(&blob_requests, is_low_priority),
);
rasterized_blobs.append(&mut txn.rasterized_blobs);
@ -570,9 +571,10 @@ impl LowPrioritySceneBuilder {
fn process_transaction(&mut self, mut txn: Box<Transaction>) -> Box<Transaction> {
let blob_requests = replace(&mut txn.blob_requests, Vec::new());
let is_low_priority = true;
let mut more_rasterized_blobs = txn.blob_rasterizer.as_mut().map_or(
Vec::new(),
|rasterizer| rasterizer.rasterize(&blob_requests),
|rasterizer| rasterizer.rasterize(&blob_requests, is_low_priority),
);
txn.rasterized_blobs.append(&mut more_rasterized_blobs);

Просмотреть файл

@ -14,7 +14,7 @@ use renderer::{
desc,
MAX_VERTEX_TEXTURE_WIDTH,
BlendMode, DebugFlags, ImageBufferKind, RendererError, RendererOptions,
TextureSampler, VertexArrayKind,
TextureSampler, VertexArrayKind, ShaderPrecacheFlags,
};
use gleam::gl::GlType;
@ -79,7 +79,7 @@ impl LazilyCompiledShader {
name: &'static str,
features: &[&'static str],
device: &mut Device,
precache: bool,
precache_flags: ShaderPrecacheFlags,
) -> Result<Self, ShaderError> {
let mut shader = LazilyCompiledShader {
program: None,
@ -88,16 +88,12 @@ impl LazilyCompiledShader {
features: features.to_vec(),
};
if precache {
if precache_flags.intersects(ShaderPrecacheFlags::ASYNC_COMPILE | ShaderPrecacheFlags::FULL_COMPILE) {
let t0 = precise_time_ns();
let program = shader.get(device)?;
shader.get_internal(device, precache_flags)?;
let t1 = precise_time_ns();
device.bind_program(program);
device.draw_triangles_u16(0, 3);
let t2 = precise_time_ns();
debug!("[C: {:.1} ms D: {:.1} ms] Precache {} {:?}",
debug!("[C: {:.1} ms ] Precache {} {:?}",
(t1 - t0) as f64 / 1000000.0,
(t2 - t1) as f64 / 1000000.0,
name,
features
);
@ -123,32 +119,32 @@ impl LazilyCompiledShader {
device.set_uniforms(program, projection);
}
fn get(&mut self, device: &mut Device) -> Result<&Program, ShaderError> {
fn get_internal(
&mut self,
device: &mut Device,
precache_flags: ShaderPrecacheFlags,
) -> Result<&mut Program, ShaderError> {
if self.program.is_none() {
let program = match self.kind {
ShaderKind::Primitive | ShaderKind::Brush | ShaderKind::Text => {
create_prim_shader(self.name,
device,
&self.features,
VertexArrayKind::Primitive)
&self.features)
}
ShaderKind::Cache(format) => {
ShaderKind::Cache(..) => {
create_prim_shader(self.name,
device,
&self.features,
format)
&self.features)
}
ShaderKind::VectorStencil => {
create_prim_shader(self.name,
device,
&self.features,
VertexArrayKind::VectorStencil)
&self.features)
}
ShaderKind::VectorCover => {
create_prim_shader(self.name,
device,
&self.features,
VertexArrayKind::VectorCover)
&self.features)
}
ShaderKind::ClipCache => {
create_clip_shader(self.name, device)
@ -157,7 +153,71 @@ impl LazilyCompiledShader {
self.program = Some(program?);
}
Ok(self.program.as_ref().unwrap())
let program = self.program.as_mut().unwrap();
if precache_flags.contains(ShaderPrecacheFlags::FULL_COMPILE) && !program.is_initialized() {
let vertex_format = match self.kind {
ShaderKind::Primitive |
ShaderKind::Brush |
ShaderKind::Text => VertexArrayKind::Primitive,
ShaderKind::Cache(format) => format,
ShaderKind::VectorStencil => VertexArrayKind::VectorStencil,
ShaderKind::VectorCover => VertexArrayKind::VectorCover,
ShaderKind::ClipCache => VertexArrayKind::Clip,
};
let vertex_descriptor = match vertex_format {
VertexArrayKind::Primitive => &desc::PRIM_INSTANCES,
VertexArrayKind::Blur => &desc::BLUR,
VertexArrayKind::Clip => &desc::CLIP,
VertexArrayKind::VectorStencil => &desc::VECTOR_STENCIL,
VertexArrayKind::VectorCover => &desc::VECTOR_COVER,
VertexArrayKind::Border => &desc::BORDER,
VertexArrayKind::Scale => &desc::SCALE,
};
device.link_program(program, vertex_descriptor)?;
device.bind_program(program);
match self.kind {
ShaderKind::ClipCache => {
device.bind_shader_samplers(
&program,
&[
("sColor0", TextureSampler::Color0),
("sTransformPalette", TextureSampler::TransformPalette),
("sRenderTasks", TextureSampler::RenderTasks),
("sGpuCache", TextureSampler::GpuCache),
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
],
);
}
_ => {
device.bind_shader_samplers(
&program,
&[
("sColor0", TextureSampler::Color0),
("sColor1", TextureSampler::Color1),
("sColor2", TextureSampler::Color2),
("sDither", TextureSampler::Dither),
("sPrevPassAlpha", TextureSampler::PrevPassAlpha),
("sPrevPassColor", TextureSampler::PrevPassColor),
("sTransformPalette", TextureSampler::TransformPalette),
("sRenderTasks", TextureSampler::RenderTasks),
("sGpuCache", TextureSampler::GpuCache),
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
],
);
}
}
}
Ok(program)
}
fn get(&mut self, device: &mut Device) -> Result<&mut Program, ShaderError> {
self.get_internal(device, ShaderPrecacheFlags::FULL_COMPILE)
}
fn deinit(self, device: &mut Device) {
@ -190,7 +250,7 @@ impl BrushShader {
name: &'static str,
device: &mut Device,
features: &[&'static str],
precache: bool,
precache_flags: ShaderPrecacheFlags,
dual_source: bool,
) -> Result<Self, ShaderError> {
let opaque = LazilyCompiledShader::new(
@ -198,7 +258,7 @@ impl BrushShader {
name,
features,
device,
precache,
precache_flags,
)?;
let mut alpha_features = features.to_vec();
@ -209,7 +269,7 @@ impl BrushShader {
name,
&alpha_features,
device,
precache,
precache_flags,
)?;
let dual_source = if dual_source {
@ -221,7 +281,7 @@ impl BrushShader {
name,
&dual_source_features,
device,
precache,
precache_flags,
)?;
Some(shader)
@ -237,7 +297,7 @@ impl BrushShader {
name,
&debug_overdraw_features,
device,
precache,
precache_flags,
)?;
Ok(BrushShader {
@ -287,14 +347,14 @@ impl TextShader {
name: &'static str,
device: &mut Device,
features: &[&'static str],
precache: bool,
precache_flags: ShaderPrecacheFlags,
) -> Result<Self, ShaderError> {
let simple = LazilyCompiledShader::new(
ShaderKind::Text,
name,
features,
device,
precache,
precache_flags,
)?;
let mut glyph_transform_features = features.to_vec();
@ -305,7 +365,7 @@ impl TextShader {
name,
&glyph_transform_features,
device,
precache,
precache_flags,
)?;
let mut debug_overdraw_features = features.to_vec();
@ -316,7 +376,7 @@ impl TextShader {
name,
&debug_overdraw_features,
device,
precache,
precache_flags,
)?;
Ok(TextShader { simple, glyph_transform, debug_overdraw })
@ -349,7 +409,6 @@ fn create_prim_shader(
name: &'static str,
device: &mut Device,
features: &[&'static str],
vertex_format: VertexArrayKind,
) -> Result<Program, ShaderError> {
let mut prefix = format!(
"#define WR_MAX_VERTEX_TEXTURE_WIDTH {}U\n",
@ -362,38 +421,7 @@ fn create_prim_shader(
debug!("PrimShader {}", name);
let vertex_descriptor = match vertex_format {
VertexArrayKind::Primitive => desc::PRIM_INSTANCES,
VertexArrayKind::Blur => desc::BLUR,
VertexArrayKind::Clip => desc::CLIP,
VertexArrayKind::VectorStencil => desc::VECTOR_STENCIL,
VertexArrayKind::VectorCover => desc::VECTOR_COVER,
VertexArrayKind::Border => desc::BORDER,
VertexArrayKind::Scale => desc::SCALE,
};
let program = device.create_program(name, &prefix, &vertex_descriptor);
if let Ok(ref program) = program {
device.bind_shader_samplers(
program,
&[
("sColor0", TextureSampler::Color0),
("sColor1", TextureSampler::Color1),
("sColor2", TextureSampler::Color2),
("sDither", TextureSampler::Dither),
("sPrevPassAlpha", TextureSampler::PrevPassAlpha),
("sPrevPassColor", TextureSampler::PrevPassColor),
("sTransformPalette", TextureSampler::TransformPalette),
("sRenderTasks", TextureSampler::RenderTasks),
("sGpuCache", TextureSampler::GpuCache),
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
],
);
}
program
device.create_program(name, &prefix)
}
fn create_clip_shader(name: &'static str, device: &mut Device) -> Result<Program, ShaderError> {
@ -404,23 +432,7 @@ fn create_clip_shader(name: &'static str, device: &mut Device) -> Result<Program
debug!("ClipShader {}", name);
let program = device.create_program(name, &prefix, &desc::CLIP);
if let Ok(ref program) = program {
device.bind_shader_samplers(
program,
&[
("sColor0", TextureSampler::Color0),
("sTransformPalette", TextureSampler::TransformPalette),
("sRenderTasks", TextureSampler::RenderTasks),
("sGpuCache", TextureSampler::GpuCache),
("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
],
);
}
program
device.create_program(name, &prefix)
}
// NB: If you add a new shader here, make sure to deinitialize it
@ -472,20 +484,11 @@ impl Shaders {
gl_type: GlType,
options: &RendererOptions,
) -> Result<Self, ShaderError> {
// needed for the precache fake draws
let dummy_vao = if options.precache_shaders {
let vao = device.create_custom_vao(&[]);
device.bind_custom_vao(&vao);
Some(vao)
} else {
None
};
let brush_solid = BrushShader::new(
"brush_solid",
device,
&[],
options.precache_shaders,
options.precache_flags,
false,
)?;
@ -493,7 +496,7 @@ impl Shaders {
"brush_blend",
device,
&[],
options.precache_shaders,
options.precache_flags,
false,
)?;
@ -501,7 +504,7 @@ impl Shaders {
"brush_mix_blend",
device,
&[],
options.precache_shaders,
options.precache_flags,
false,
)?;
@ -513,7 +516,7 @@ impl Shaders {
} else {
&[]
},
options.precache_shaders,
options.precache_flags,
false,
)?;
@ -525,7 +528,7 @@ impl Shaders {
} else {
&[]
},
options.precache_shaders,
options.precache_flags,
false,
)?;
@ -534,7 +537,7 @@ impl Shaders {
"cs_blur",
&["ALPHA_TARGET"],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_blur_rgba8 = LazilyCompiledShader::new(
@ -542,7 +545,7 @@ impl Shaders {
"cs_blur",
&["COLOR_TARGET"],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_clip_rectangle = LazilyCompiledShader::new(
@ -550,7 +553,7 @@ impl Shaders {
"cs_clip_rectangle",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_clip_box_shadow = LazilyCompiledShader::new(
@ -558,7 +561,7 @@ impl Shaders {
"cs_clip_box_shadow",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_clip_line = LazilyCompiledShader::new(
@ -566,7 +569,7 @@ impl Shaders {
"cs_clip_line",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_clip_image = LazilyCompiledShader::new(
@ -574,7 +577,7 @@ impl Shaders {
"cs_clip_image",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_scale_a8 = LazilyCompiledShader::new(
@ -582,7 +585,7 @@ impl Shaders {
"cs_scale",
&["ALPHA_TARGET"],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_scale_rgba8 = LazilyCompiledShader::new(
@ -590,19 +593,25 @@ impl Shaders {
"cs_scale",
&["COLOR_TARGET"],
device,
options.precache_shaders,
options.precache_flags,
)?;
let ps_text_run = TextShader::new("ps_text_run",
device,
&[],
options.precache_shaders,
options.precache_flags,
)?;
let dual_source_precache_flags = if options.disable_dual_source_blending {
ShaderPrecacheFlags::empty()
} else {
options.precache_flags
};
let ps_text_run_dual_source = TextShader::new("ps_text_run",
device,
&[DUAL_SOURCE_FEATURE],
options.precache_shaders && !options.disable_dual_source_blending,
dual_source_precache_flags,
)?;
// All image configuration.
@ -622,7 +631,7 @@ impl Shaders {
"brush_image",
device,
&image_features,
options.precache_shaders,
options.precache_flags,
!options.disable_dual_source_blending,
)?);
}
@ -658,7 +667,7 @@ impl Shaders {
"brush_yuv_image",
device,
&yuv_features,
options.precache_shaders,
options.precache_flags,
false,
)?;
let index = Self::get_yuv_shader_index(
@ -678,7 +687,7 @@ impl Shaders {
"cs_border_segment",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
let cs_border_solid = LazilyCompiledShader::new(
@ -686,7 +695,7 @@ impl Shaders {
"cs_border_solid",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
let ps_split_composite = LazilyCompiledShader::new(
@ -694,13 +703,9 @@ impl Shaders {
"ps_split_composite",
&[],
device,
options.precache_shaders,
options.precache_flags,
)?;
if let Some(vao) = dummy_vao {
device.delete_custom_vao(vao);
}
Ok(Shaders {
cs_blur_a8,
cs_blur_rgba8,

Просмотреть файл

@ -83,10 +83,12 @@ impl ScaleOffset {
}
pub fn offset(&self, offset: Vector2D<f32>) -> Self {
ScaleOffset {
scale: self.scale,
offset: self.offset + offset,
}
self.accumulate(
&ScaleOffset {
scale: Vector2D::new(1.0, 1.0),
offset,
}
)
}
// Produce a ScaleOffset that includes both self
@ -105,20 +107,6 @@ impl ScaleOffset {
}
}
// Find the difference between two ScaleOffset types.
pub fn difference(&self, other: &ScaleOffset) -> Self {
ScaleOffset {
scale: Vector2D::new(
other.scale.x / self.scale.x,
other.scale.y / self.scale.y,
),
offset: Vector2D::new(
(other.offset.x - self.offset.x) / self.scale.x,
(other.offset.y - self.offset.y) / self.scale.y,
),
}
}
pub fn map_rect<F, T>(&self, rect: &TypedRect<f32, F>) -> TypedRect<f32, T> {
TypedRect::new(
TypedPoint2D::new(
@ -378,6 +366,7 @@ pub fn extract_inner_rect_safe<U>(
#[cfg(test)]
pub mod test {
use api::{LayoutTransform, LayoutVector3D};
use super::*;
use euclid::{Point2D, Angle, Transform3D};
use std::f32::consts::PI;
@ -392,6 +381,76 @@ pub mod test {
// rotation by 60 degrees would imply scaling of X component by a factor of 2
assert_eq!(m1.inverse_project(&p0), Some(Point2D::new(2.0, 2.0)));
}
fn validate_convert(xref: &LayoutTransform) {
let so = ScaleOffset::from_transform(xref).unwrap();
let xf = so.to_transform();
assert!(xref.approx_eq(&xf));
}
#[test]
fn scale_offset_convert() {
let xref = LayoutTransform::create_translation(130.0, 200.0, 0.0);
validate_convert(&xref);
let xref = LayoutTransform::create_scale(13.0, 8.0, 1.0);
validate_convert(&xref);
let xref = LayoutTransform::create_scale(0.5, 0.5, 1.0)
.pre_translate(LayoutVector3D::new(124.0, 38.0, 0.0));
validate_convert(&xref);
let xref = LayoutTransform::create_translation(50.0, 240.0, 0.0)
.pre_mul(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
validate_convert(&xref);
}
fn validate_inverse(xref: &LayoutTransform) {
let s0 = ScaleOffset::from_transform(xref).unwrap();
let s1 = s0.inverse().accumulate(&s0);
assert!((s1.scale.x - 1.0).abs() < NEARLY_ZERO &&
(s1.scale.y - 1.0).abs() < NEARLY_ZERO &&
s1.offset.x.abs() < NEARLY_ZERO &&
s1.offset.y.abs() < NEARLY_ZERO,
"{:?}",
s1);
}
#[test]
fn scale_offset_inverse() {
let xref = LayoutTransform::create_translation(130.0, 200.0, 0.0);
validate_inverse(&xref);
let xref = LayoutTransform::create_scale(13.0, 8.0, 1.0);
validate_inverse(&xref);
let xref = LayoutTransform::create_scale(0.5, 0.5, 1.0)
.pre_translate(LayoutVector3D::new(124.0, 38.0, 0.0));
validate_inverse(&xref);
let xref = LayoutTransform::create_translation(50.0, 240.0, 0.0)
.pre_mul(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
validate_inverse(&xref);
}
fn validate_accumulate(x0: &LayoutTransform, x1: &LayoutTransform) {
let x = x0.pre_mul(x1);
let s0 = ScaleOffset::from_transform(x0).unwrap();
let s1 = ScaleOffset::from_transform(x1).unwrap();
let s = s0.accumulate(&s1).to_transform();
assert!(x.approx_eq(&s), "{:?}\n{:?}", x, s);
}
#[test]
fn scale_offset_accumulate() {
let x0 = LayoutTransform::create_translation(130.0, 200.0, 0.0);
let x1 = LayoutTransform::create_scale(7.0, 3.0, 1.0);
validate_accumulate(&x0, &x1);
}
}
pub trait MaxRect {

Просмотреть файл

@ -19,7 +19,7 @@ struct Shader {
const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024U\n";
const BRUSH_FEATURES: &[&str] = &["", "ALPHA_PASS"];
const CLIP_FEATURES: &[&str] = &["TRANSFORM"];
const CLIP_FEATURES: &[&str] = &[""];
const CACHE_FEATURES: &[&str] = &[""];
const GRADIENT_FEATURES: &[&str] = &[ "", "DITHERING", "ALPHA_PASS", "DITHERING,ALPHA_PASS" ];
const PRIM_FEATURES: &[&str] = &[""];

Просмотреть файл

@ -343,7 +343,14 @@ pub trait BlobImageHandler: Send {
/// A group of rasterization requests to execute synchronously on the scene builder thread.
pub trait AsyncBlobImageRasterizer : Send {
/// Rasterize the requests.
fn rasterize(&mut self, requests: &[BlobImageParams]) -> Vec<(BlobImageRequest, BlobImageResult)>;
///
/// Gecko uses te priority hint to schedule work in a way that minimizes the risk
/// of high priority work being blocked by (or enqued behind) low priority work.
fn rasterize(
&mut self,
requests: &[BlobImageParams],
low_priority: bool
) -> Vec<(BlobImageRequest, BlobImageResult)>;
}

Просмотреть файл

@ -1 +1 @@
9536249e3ed920a920346f6cc0a79473cad16099
3c3f9a4e919b81639f078d7bd101012de61b9396

Просмотреть файл

@ -0,0 +1,11 @@
--- bindings.rs
+++ bindings.rs
@@ -1017,7 +1023,7 @@
sampler: Some(Box::new(SamplerCallback::new(window_id))),
max_texture_size: Some(8192), // Moz2D doesn't like textures bigger than this
clear_color: Some(ColorF::new(0.0, 0.0, 0.0, 0.0)),
- precache_shaders: env_var_to_bool("MOZ_WR_PRECACHE_SHADERS"),
+ precache_flags,
..Default::default()
};

Просмотреть файл

@ -183,7 +183,11 @@ struct Rasterizer {
}
impl AsyncBlobImageRasterizer for Rasterizer {
fn rasterize(&mut self, requests: &[BlobImageParams]) -> Vec<(BlobImageRequest, BlobImageResult)> {
fn rasterize(
&mut self,
requests: &[BlobImageParams],
_low_priority: bool
) -> Vec<(BlobImageRequest, BlobImageResult)> {
let requests: Vec<Command> = requests.into_iter().map(
|item| {
let (color, tile_size) = self.image_cmds[&item.request.key];

Просмотреть файл

@ -20,7 +20,7 @@ use std::sync::mpsc::Receiver;
use time;
use webrender;
use webrender::api::*;
use webrender::{DebugFlags, RendererStats};
use webrender::{DebugFlags, RendererStats, ShaderPrecacheFlags};
use yaml_frame_writer::YamlFrameWriterReceiver;
use {WindowWrapper, NotifierEvent};
@ -205,6 +205,12 @@ impl Wrench {
debug_flags.set(DebugFlags::DISABLE_BATCHING, no_batch);
let callbacks = Arc::new(Mutex::new(blob::BlobCallbacks::new()));
let precache_flags = if precache_shaders {
ShaderPrecacheFlags::FULL_COMPILE
} else {
ShaderPrecacheFlags::empty()
};
let opts = webrender::RendererOptions {
device_pixel_ratio: dp_ratio,
resource_override_path: shader_override_path,
@ -213,7 +219,7 @@ impl Wrench {
debug_flags,
enable_clear_scissor: !no_scissor,
max_recorded_profiles: 16,
precache_shaders,
precache_flags,
blob_image_handler: Some(Box::new(blob::CheckerboardRenderer::new(callbacks.clone()))),
disable_dual_source_blending,
chase_primitive,