зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1496171. Update webrender to commit 3c3f9a4e919b81639f078d7bd101012de61b9396
This commit is contained in:
Родитель
1e79f89539
Коммит
1ddc54bd0f
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче