From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- gfx/wr/Cargo.lock | 19 +- gfx/wr/peek-poke/peek-poke-derive/src/lib.rs | 21 +- gfx/wr/webrender/Cargo.toml | 6 +- gfx/wr/webrender/res/brush.glsl | 2 +- gfx/wr/webrender/res/brush_linear_gradient.glsl | 4 +- gfx/wr/webrender/res/cs_border_segment.glsl | 8 +- gfx/wr/webrender/res/cs_clip_image.glsl | 117 -------- gfx/wr/webrender/res/cs_linear_gradient.glsl | 4 +- gfx/wr/webrender/res/cs_radial_gradient.glsl | 4 +- gfx/wr/webrender/res/gpu_buffer.glsl | 36 ++- gfx/wr/webrender/res/gradient.glsl | 2 +- gfx/wr/webrender/res/prim_shared.glsl | 6 +- gfx/wr/webrender/res/ps_quad.glsl | 81 ++++-- gfx/wr/webrender/res/ps_quad_mask.glsl | 6 +- gfx/wr/webrender/res/ps_quad_textured.glsl | 2 + gfx/wr/webrender/res/ps_text_run.glsl | 2 +- gfx/wr/webrender/res/render_task.glsl | 25 +- gfx/wr/webrender/src/batch.rs | 215 +++++++++----- gfx/wr/webrender/src/device/gl.rs | 10 +- gfx/wr/webrender/src/frame_builder.rs | 44 ++- gfx/wr/webrender/src/gpu_types.rs | 56 ++-- gfx/wr/webrender/src/picture.rs | 57 ++-- gfx/wr/webrender/src/prepare.rs | 313 +++++++++++---------- gfx/wr/webrender/src/prim_store/gradient/conic.rs | 2 +- gfx/wr/webrender/src/prim_store/gradient/linear.rs | 4 +- gfx/wr/webrender/src/prim_store/gradient/mod.rs | 4 +- gfx/wr/webrender/src/prim_store/gradient/radial.rs | 2 +- gfx/wr/webrender/src/prim_store/image.rs | 2 +- gfx/wr/webrender/src/prim_store/mod.rs | 31 ++ gfx/wr/webrender/src/render_target.rs | 27 +- gfx/wr/webrender/src/render_task.rs | 27 +- gfx/wr/webrender/src/render_task_cache.rs | 6 +- gfx/wr/webrender/src/render_task_graph.rs | 7 + gfx/wr/webrender/src/renderer/gpu_buffer.rs | 173 ++++++++---- gfx/wr/webrender/src/renderer/mod.rs | 121 ++++---- gfx/wr/webrender/src/renderer/shade.rs | 20 +- gfx/wr/webrender/src/renderer/upload.rs | 12 +- gfx/wr/webrender/src/renderer/vertex.rs | 67 +---- gfx/wr/webrender/src/resource_cache.rs | 10 +- gfx/wr/webrender/src/spatial_node.rs | 2 +- gfx/wr/webrender/src/spatial_tree.rs | 43 +++ gfx/wr/webrender/src/telemetry.rs | 8 +- gfx/wr/webrender_api/src/font.rs | 22 +- gfx/wr/webrender_build/src/shader_features.rs | 1 - gfx/wr/wr_glyph_rasterizer/Cargo.toml | 6 +- gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs | 10 +- gfx/wr/wr_glyph_rasterizer/src/lib.rs | 10 +- 47 files changed, 880 insertions(+), 777 deletions(-) delete mode 100644 gfx/wr/webrender/res/cs_clip_image.glsl (limited to 'gfx/wr') diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock index 02491f3993..2bf28a1b6e 100644 --- a/gfx/wr/Cargo.lock +++ b/gfx/wr/Cargo.lock @@ -996,29 +996,22 @@ dependencies = [ [[package]] name = "glean" -version = "57.0.0" +version = "58.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a" +checksum = "f58388f10d013e2d12bb58e6e76983ede120789956fe827913a3d2560c66d44d" dependencies = [ - "chrono", - "crossbeam-channel", "glean-core", "inherent", "log", "once_cell", - "serde", - "serde_json", - "thiserror", - "time", - "uuid", "whatsys", ] [[package]] name = "glean-core" -version = "57.0.0" +version = "58.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6831cadd28b625bc296732d71dc7c978f208ba27911cad072785f87f23b1e634" +checksum = "ed9acc46fd38c5c995a0537e76364496addace660839dc279079e5957e3c1093" dependencies = [ "android_logger", "bincode", @@ -1121,9 +1114,9 @@ dependencies = [ [[package]] name = "glslopt" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a3f5c04450dfdadb4b08f6e5ee6f5110f674de1acbd6199bfec68392a8cbaf" +checksum = "ee5be629003d587bab188f3e2e3b010aa2cde7c41ec967b3a244f388d4d81877" dependencies = [ "cc", ] diff --git a/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs b/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs index ac20b2b922..9e26b22fba 100644 --- a/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs +++ b/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs @@ -12,23 +12,6 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{Ident, Index, TraitBound}; use synstructure::{decl_derive, Structure, BindStyle, AddBounds}; -use unicode_xid::UnicodeXID; - -// Internal method for sanitizing an identifier for hygiene purposes. -fn sanitize_ident(s: &str) -> Ident { - let mut res = String::with_capacity(s.len()); - for mut c in s.chars() { - if !UnicodeXID::is_xid_continue(c) { - c = '_' - } - // Deduplicate consecutive _ characters. - if res.ends_with('_') && c == '_' { - continue; - } - res.push(c); - } - Ident::new(&res, Span::call_site()) -} /// Calculates size type for number of variants (used for enums) fn get_discriminant_size_type(len: usize) -> TokenStream { @@ -241,11 +224,9 @@ fn peek_poke_derive(mut s: Structure) -> TokenStream { s.add_trait_bounds(&default_trait, &mut where_clause, AddBounds::Generics); s.add_trait_bounds(&peek_trait, &mut where_clause, AddBounds::Generics); - let dummy_const: Ident = sanitize_ident(&format!("_DERIVE_peek_poke_Peek_FOR_{}", name)); - let peek_impl = quote! { #[allow(non_upper_case_globals)] - const #dummy_const: () = { + const _: () = { extern crate peek_poke; impl #impl_generics peek_poke::Peek for #name #ty_generics #where_clause { diff --git a/gfx/wr/webrender/Cargo.toml b/gfx/wr/webrender/Cargo.toml index ed364fc34d..506226beca 100644 --- a/gfx/wr/webrender/Cargo.toml +++ b/gfx/wr/webrender/Cargo.toml @@ -18,12 +18,12 @@ serialize_program = ["serde", "webrender_build/serialize_program"] dynamic_freetype = ["glyph_rasterizer/dynamic_freetype"] static_freetype = ["glyph_rasterizer/static_freetype"] leak_checks = [] -gecko = ["firefox-on-glean", "glyph_rasterizer/gecko"] +gecko = ["firefox-on-glean", "glean", "glyph_rasterizer/gecko"] sw_compositor = ["swgl"] [build-dependencies] build-parallel = "0.1.2" -glslopt = "0.1.9" +glslopt = "0.1.10" webrender_build = { version = "0.0.2", path = "../webrender_build" } [dependencies] @@ -52,7 +52,7 @@ svg_fmt = "0.4" tracy-rs = "0.1.2" derive_more = { version = "0.99", default-features = false, features = ["add_assign"] } etagere = "0.2.6" -glean = "57.0.0" +glean = { version = "58.1.0", optional = true } firefox-on-glean = { version = "0.1.0", optional = true } swgl = { path = "../swgl", optional = true } topological-sort = "0.1" diff --git a/gfx/wr/webrender/res/brush.glsl b/gfx/wr/webrender/res/brush.glsl index 8d0d52ce82..67c9255831 100644 --- a/gfx/wr/webrender/res/brush.glsl +++ b/gfx/wr/webrender/res/brush.glsl @@ -214,7 +214,7 @@ void main(void) { Instance instance = decode_instance_attributes(); PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address); Transform transform = fetch_transform(ph.transform_id); - PictureTask task = fetch_picture_task(instance.picture_task_address); + PictureTask task = fetch_picture_task(ph.picture_task_address); ClipArea clip_area = fetch_clip_area(instance.clip_address); WR_VERTEX_SHADER_MAIN_FUNCTION(instance, ph, transform, task, clip_area); diff --git a/gfx/wr/webrender/res/brush_linear_gradient.glsl b/gfx/wr/webrender/res/brush_linear_gradient.glsl index ceb1b14e5b..235be4b24b 100644 --- a/gfx/wr/webrender/res/brush_linear_gradient.glsl +++ b/gfx/wr/webrender/res/brush_linear_gradient.glsl @@ -82,12 +82,12 @@ Fragment brush_fs() { #ifdef SWGL_DRAW_SPAN void swgl_drawSpanRGBA8() { - int address = swgl_validateGradient(sGpuBuffer, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0)); + int address = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0)); if (address < 0) { return; } - swgl_commitLinearGradientRGBA8(sGpuBuffer, address, GRADIENT_ENTRIES, true, v_gradient_repeat.x != 0.0, + swgl_commitLinearGradientRGBA8(sGpuBufferF, address, GRADIENT_ENTRIES, true, v_gradient_repeat.x != 0.0, v_pos, v_scale_dir, v_start_offset.x); } #endif diff --git a/gfx/wr/webrender/res/cs_border_segment.glsl b/gfx/wr/webrender/res/cs_border_segment.glsl index e684bfa6df..7deb62f6ef 100644 --- a/gfx/wr/webrender/res/cs_border_segment.glsl +++ b/gfx/wr/webrender/res/cs_border_segment.glsl @@ -13,7 +13,7 @@ flat varying mediump vec4 vColor11; // A point + tangent defining the line where the edge // transition occurs. Used for corners only. -flat varying mediump vec4 vColorLine; +flat varying highp vec4 vColorLine; // x: segment, y: clip mode // We cast these to/from floats rather than using an ivec due to a driver bug @@ -31,13 +31,13 @@ flat varying highp vec4 vClipCenter_Sign; // An outer and inner elliptical radii for border // corner clipping. -flat varying mediump vec4 vClipRadii; +flat varying highp vec4 vClipRadii; // Reference point for determine edge clip lines. -flat varying mediump vec4 vEdgeReference; +flat varying highp vec4 vEdgeReference; // Stores widths/2 and widths/3 to save doing this in FS. -flat varying mediump vec4 vPartialWidths; +flat varying highp vec4 vPartialWidths; // Clipping parameters for dot or dash. flat varying mediump vec4 vClipParams1; diff --git a/gfx/wr/webrender/res/cs_clip_image.glsl b/gfx/wr/webrender/res/cs_clip_image.glsl deleted file mode 100644 index 24ba1dab8e..0000000000 --- a/gfx/wr/webrender/res/cs_clip_image.glsl +++ /dev/null @@ -1,117 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include shared,clip_shared - -varying highp vec2 vLocalPos; -varying highp vec2 vClipMaskImageUv; - -flat varying highp vec4 vClipMaskUvInnerRect; - -#ifdef WR_VERTEX_SHADER - -PER_INSTANCE in vec4 aClipTileRect; -PER_INSTANCE in ivec2 aClipDataResourceAddress; -PER_INSTANCE in vec4 aClipLocalRect; - -struct ClipMaskInstanceImage { - ClipMaskInstanceCommon base; - RectWithEndpoint tile_rect; - ivec2 resource_address; - RectWithEndpoint local_rect; -}; - -ClipMaskInstanceImage fetch_clip_item() { - ClipMaskInstanceImage cmi; - - cmi.base = fetch_clip_item_common(); - - cmi.tile_rect = RectWithEndpoint(aClipTileRect.xy, aClipTileRect.zw); - cmi.resource_address = aClipDataResourceAddress; - cmi.local_rect = RectWithEndpoint(aClipLocalRect.xy, aClipLocalRect.zw); - - return cmi; -} - -struct ClipImageVertexInfo { - vec2 local_pos; - vec4 world_pos; -}; - -// This differs from write_clip_tile_vertex in that we forward transform the -// primitive's local-space tile rect into the target space. We use scissoring -// to ensure that the primitive does not draw outside the target bounds. -ClipImageVertexInfo write_clip_image_vertex(RectWithEndpoint tile_rect, - RectWithEndpoint local_clip_rect, - Transform prim_transform, - Transform clip_transform, - RectWithEndpoint sub_rect, - vec2 task_origin, - vec2 screen_origin, - float device_pixel_scale) { - vec2 local_pos = rect_clamp(local_clip_rect, mix(tile_rect.p0, tile_rect.p1, aPosition.xy)); - vec4 world_pos = prim_transform.m * vec4(local_pos, 0.0, 1.0); - vec4 final_pos = vec4( - world_pos.xy * device_pixel_scale + (task_origin - screen_origin) * world_pos.w, - 0.0, - world_pos.w - ); - gl_Position = uTransform * final_pos; - - init_transform_vs( - clip_transform.is_axis_aligned - ? vec4(vec2(-1.0e16), vec2(1.0e16)) - : vec4(local_clip_rect.p0, local_clip_rect.p1)); - - ClipImageVertexInfo vi = ClipImageVertexInfo(local_pos, world_pos); - return vi; -} - -void main(void) { - ClipMaskInstanceImage cmi = fetch_clip_item(); - Transform clip_transform = fetch_transform(cmi.base.clip_transform_id); - Transform prim_transform = fetch_transform(cmi.base.prim_transform_id); - ImageSource res = fetch_image_source_direct(cmi.resource_address); - - ClipImageVertexInfo vi = write_clip_image_vertex( - cmi.tile_rect, - cmi.local_rect, - prim_transform, - clip_transform, - cmi.base.sub_rect, - cmi.base.task_origin, - cmi.base.screen_origin, - cmi.base.device_pixel_scale - ); - vLocalPos = vi.local_pos; - vec2 uv = (vi.local_pos - cmi.tile_rect.p0) / rect_size(cmi.tile_rect); - - vec2 texture_size = vec2(TEX_SIZE(sColor0)); - vec4 uv_rect = vec4(res.uv_rect.p0, res.uv_rect.p1); - vClipMaskImageUv = mix(uv_rect.xy, uv_rect.zw, uv) / texture_size; - - // applying a half-texel offset to the UV boundaries to prevent linear samples from the outside - vClipMaskUvInnerRect = (uv_rect + vec4(0.5, 0.5, -0.5, -0.5)) / texture_size.xyxy; -} -#endif - -#ifdef WR_FRAGMENT_SHADER -void main(void) { - float alpha = init_transform_rough_fs(vLocalPos); - vec2 source_uv = clamp(vClipMaskImageUv, vClipMaskUvInnerRect.xy, vClipMaskUvInnerRect.zw); - float clip_alpha = texture(sColor0, source_uv).r; //careful: texture has type A8 - oFragColor = vec4(mix(1.0, clip_alpha, alpha), 0.0, 0.0, 1.0); -} - -#ifdef SWGL_DRAW_SPAN -void swgl_drawSpanR8() { - if (has_valid_transform_bounds()) { - return; - } - - swgl_commitTextureLinearR8(sColor0, vClipMaskImageUv, vClipMaskUvInnerRect); -} -#endif - -#endif diff --git a/gfx/wr/webrender/res/cs_linear_gradient.glsl b/gfx/wr/webrender/res/cs_linear_gradient.glsl index b1aff899a6..1afee5818b 100644 --- a/gfx/wr/webrender/res/cs_linear_gradient.glsl +++ b/gfx/wr/webrender/res/cs_linear_gradient.glsl @@ -54,12 +54,12 @@ void main(void) { #ifdef SWGL_DRAW_SPAN void swgl_drawSpanRGBA8() { - int address = swgl_validateGradient(sGpuBuffer, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0)); + int address = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0)); if (address < 0) { return; } - swgl_commitLinearGradientRGBA8(sGpuBuffer, address, GRADIENT_ENTRIES, false, v_gradient_repeat.x != 0.0, + swgl_commitLinearGradientRGBA8(sGpuBufferF, address, GRADIENT_ENTRIES, false, v_gradient_repeat.x != 0.0, v_pos, v_scale_dir, v_start_offset.x); } #endif diff --git a/gfx/wr/webrender/res/cs_radial_gradient.glsl b/gfx/wr/webrender/res/cs_radial_gradient.glsl index 16ffe06376..10919ac628 100644 --- a/gfx/wr/webrender/res/cs_radial_gradient.glsl +++ b/gfx/wr/webrender/res/cs_radial_gradient.glsl @@ -58,12 +58,12 @@ void main(void) { #ifdef SWGL_DRAW_SPAN void swgl_drawSpanRGBA8() { - int address = swgl_validateGradient(sGpuBuffer, get_gpu_buffer_uv(v_gradient_address.x), + int address = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(v_gradient_address.x), int(GRADIENT_ENTRIES + 2.0)); if (address < 0) { return; } - swgl_commitRadialGradientRGBA8(sGpuBuffer, address, GRADIENT_ENTRIES, v_gradient_repeat.x != 0.0, + swgl_commitRadialGradientRGBA8(sGpuBufferF, address, GRADIENT_ENTRIES, v_gradient_repeat.x != 0.0, v_pos, v_start_radius.x); } #endif diff --git a/gfx/wr/webrender/res/gpu_buffer.glsl b/gfx/wr/webrender/res/gpu_buffer.glsl index 25f4622db2..4923a28ef9 100644 --- a/gfx/wr/webrender/res/gpu_buffer.glsl +++ b/gfx/wr/webrender/res/gpu_buffer.glsl @@ -2,41 +2,47 @@ * 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/. */ -uniform HIGHP_SAMPLER_FLOAT sampler2D sGpuBuffer; +uniform HIGHP_SAMPLER_FLOAT sampler2D sGpuBufferF; +uniform HIGHP_SAMPLER_FLOAT isampler2D sGpuBufferI; ivec2 get_gpu_buffer_uv(HIGHP_FS_ADDRESS int address) { return ivec2(uint(address) % WR_MAX_VERTEX_TEXTURE_WIDTH, uint(address) / WR_MAX_VERTEX_TEXTURE_WIDTH); } -vec4 fetch_from_gpu_buffer_1(HIGHP_FS_ADDRESS int address) { +vec4 fetch_from_gpu_buffer_1f(HIGHP_FS_ADDRESS int address) { ivec2 uv = get_gpu_buffer_uv(address); - return texelFetch(sGpuBuffer, uv, 0); + return texelFetch(sGpuBufferF, uv, 0); } -vec4[2] fetch_from_gpu_buffer_2(HIGHP_FS_ADDRESS int address) { +vec4[2] fetch_from_gpu_buffer_2f(HIGHP_FS_ADDRESS int address) { ivec2 uv = get_gpu_buffer_uv(address); return vec4[2]( - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(0, 0)), - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(1, 0)) + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)) ); } -vec4[3] fetch_from_gpu_buffer_3(HIGHP_FS_ADDRESS int address) { +vec4[3] fetch_from_gpu_buffer_3f(HIGHP_FS_ADDRESS int address) { ivec2 uv = get_gpu_buffer_uv(address); return vec4[3]( - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(0, 0)), - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(1, 0)), - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(2, 0)) + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)), + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(2, 0)) ); } -vec4[4] fetch_from_gpu_buffer_4(HIGHP_FS_ADDRESS int address) { +vec4[4] fetch_from_gpu_buffer_4f(HIGHP_FS_ADDRESS int address) { ivec2 uv = get_gpu_buffer_uv(address); return vec4[4]( - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(0, 0)), - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(1, 0)), - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(2, 0)), - TEXEL_FETCH(sGpuBuffer, uv, 0, ivec2(3, 0)) + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)), + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(2, 0)), + TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(3, 0)) ); } + +ivec4 fetch_from_gpu_buffer_1i(HIGHP_FS_ADDRESS int address) { + ivec2 uv = get_gpu_buffer_uv(address); + return texelFetch(sGpuBufferI, uv, 0); +} diff --git a/gfx/wr/webrender/res/gradient.glsl b/gfx/wr/webrender/res/gradient.glsl index 87c011fefc..6ed2e69871 100644 --- a/gfx/wr/webrender/res/gradient.glsl +++ b/gfx/wr/webrender/res/gradient.glsl @@ -54,7 +54,7 @@ vec4 sample_gradient(float offset) { float entry_fract = x - entry_index; // Fetch the start and end color. There is a [start, end] color per entry. - vec4 texels[2] = fetch_from_gpu_buffer_2(v_gradient_address.x + 2 * int(entry_index)); + vec4 texels[2] = fetch_from_gpu_buffer_2f(v_gradient_address.x + 2 * int(entry_index)); // Finally interpolate and apply dithering return dither(texels[0] + texels[1] * entry_fract); diff --git a/gfx/wr/webrender/res/prim_shared.glsl b/gfx/wr/webrender/res/prim_shared.glsl index 1a599bf980..9762658776 100644 --- a/gfx/wr/webrender/res/prim_shared.glsl +++ b/gfx/wr/webrender/res/prim_shared.glsl @@ -44,7 +44,6 @@ PER_INSTANCE in ivec4 aData; struct Instance { int prim_header_address; - int picture_task_address; int clip_address; int segment_index; int flags; @@ -56,8 +55,7 @@ Instance decode_instance_attributes() { Instance instance; instance.prim_header_address = aData.x; - instance.picture_task_address = aData.y >> 16; - instance.clip_address = aData.y & 0xffff; + instance.clip_address = aData.y; instance.segment_index = aData.z & 0xffff; instance.flags = aData.z >> 16; instance.resource_address = aData.w & 0xffffff; @@ -72,6 +70,7 @@ struct PrimitiveHeader { float z; int specific_prim_address; int transform_id; + int picture_task_address; ivec4 user_data; }; @@ -90,6 +89,7 @@ PrimitiveHeader fetch_prim_header(int index) { ph.z = float(data0.x); ph.specific_prim_address = data0.y; ph.transform_id = data0.z; + ph.picture_task_address = data0.w; ph.user_data = data1; return ph; diff --git a/gfx/wr/webrender/res/ps_quad.glsl b/gfx/wr/webrender/res/ps_quad.glsl index ed6b35c3b8..94c80a93f7 100644 --- a/gfx/wr/webrender/res/ps_quad.glsl +++ b/gfx/wr/webrender/res/ps_quad.glsl @@ -2,12 +2,40 @@ * 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/. */ +/// The common infrastructure for ps_quad_* shaders. +/// +/// # Memory layout +/// +/// The diagram below shows the the various pieces of data fectched in the vertex shader: +/// +///```ascii +/// (int gpu buffer) +/// +---------------+ (sGpuCache) +/// (instance-step vertex attr) | Int header | +-----------+ +/// +-----------------------------+ | | | Transform | +/// | Quad instance (uvec4) | +--> | transform id +--> +-----------+ +/// | | | | z id | +/// | x: int prim address +---+ +---------------+ (float gpu buffer) +/// | y: float prim address +--------------------------> +-----------+--------------+-+-+ +/// | z: quad flags | (sGpuCache) | Quad Prim | Quad Segment | | | +/// | edge flags | +--------------------+ | | | | | +/// | part index | | Picture task | | bounds | rect | | | +/// | segment index | | | | clip | uv rect | | | +/// | w: picture task address +--> | task rect | | color | | | | +/// +-----------------------------+ | device pixel scale | +-----------+--------------+-+-+ +/// | content origin | +/// +--------------------+ +///``` + #define WR_FEATURE_TEXTURE_2D #include shared,rect,transform,render_task,gpu_buffer flat varying mediump vec4 v_color; flat varying mediump vec4 v_uv_sample_bounds; +// x: (in ps_quad_textured) has edge flags +// y: has uv rect +// z: (in ps_quad_textured) sample as mask flat varying lowp ivec4 v_flags; varying highp vec2 v_uv; @@ -61,7 +89,7 @@ struct QuadPrimitive { QuadSegment fetch_segment(int base, int index) { QuadSegment seg; - vec4 texels[2] = fetch_from_gpu_buffer_2(base + 3 + index * 2); + vec4 texels[2] = fetch_from_gpu_buffer_2f(base + 3 + index * 2); seg.rect = RectWithEndpoint(texels[0].xy, texels[0].zw); seg.uv_rect = texels[1]; @@ -72,7 +100,7 @@ QuadSegment fetch_segment(int base, int index) { QuadPrimitive fetch_primitive(int index) { QuadPrimitive prim; - vec4 texels[3] = fetch_from_gpu_buffer_3(index); + vec4 texels[3] = fetch_from_gpu_buffer_3f(index); prim.bounds = RectWithEndpoint(texels[0].xy, texels[0].zw); prim.clip = RectWithEndpoint(texels[1].xy, texels[1].zw); @@ -81,37 +109,51 @@ QuadPrimitive fetch_primitive(int index) { return prim; } +struct QuadHeader { + int transform_id; + int z_id; +}; + +QuadHeader fetch_header(int address) { + ivec4 header = fetch_from_gpu_buffer_1i(address); + + QuadHeader qh = QuadHeader( + header.x, + header.y + ); + + return qh; +} + struct QuadInstance { // x - int prim_address; + int prim_address_i; // y - int quad_flags; - int edge_flags; - int picture_task_address; + int prim_address_f; // z + int quad_flags; + int edge_flags; int part_index; - int z_id; + int segment_index; // w - int segment_index; - int transform_id; + int picture_task_address; }; QuadInstance decode_instance() { QuadInstance qi = QuadInstance( aData.x, - (aData.y >> 24) & 0xff, - (aData.y >> 16) & 0xff, - aData.y & 0xffff, + aData.y, (aData.z >> 24) & 0xff, - aData.z & 0xffffff, + (aData.z >> 16) & 0xff, + (aData.z >> 8) & 0xff, + (aData.z >> 0) & 0xff, - (aData.w >> 24) & 0xff, - aData.w & 0xffffff + aData.w ); return qi; @@ -165,17 +207,18 @@ float edge_aa_offset(int edge, int flags) { PrimitiveInfo ps_quad_main(void) { QuadInstance qi = decode_instance(); - Transform transform = fetch_transform(qi.transform_id); + QuadHeader qh = fetch_header(qi.prim_address_i); + Transform transform = fetch_transform(qh.transform_id); PictureTask task = fetch_picture_task(qi.picture_task_address); - QuadPrimitive prim = fetch_primitive(qi.prim_address); - float z = float(qi.z_id); + QuadPrimitive prim = fetch_primitive(qi.prim_address_f); + float z = float(qh.z_id); QuadSegment seg; if (qi.segment_index == INVALID_SEGMENT_INDEX) { seg.rect = prim.bounds; seg.uv_rect = vec4(0.0); } else { - seg = fetch_segment(qi.prim_address, qi.segment_index); + seg = fetch_segment(qi.prim_address_f, qi.segment_index); } // The local space rect that we will draw, which is effectively: diff --git a/gfx/wr/webrender/res/ps_quad_mask.glsl b/gfx/wr/webrender/res/ps_quad_mask.glsl index 4b28109726..6b72714efb 100644 --- a/gfx/wr/webrender/res/ps_quad_mask.glsl +++ b/gfx/wr/webrender/res/ps_quad_mask.glsl @@ -2,6 +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/. */ +/// This shader applies a (rounded) rectangle mask to the content of the framebuffer. + #include ps_quad,ellipse varying highp vec4 vClipLocalPos; @@ -45,12 +47,12 @@ Clip fetch_clip(int index) { clip.space = aClipData.z; #ifdef WR_FEATURE_FAST_PATH - vec4 texels[3] = fetch_from_gpu_buffer_3(index); + vec4 texels[3] = fetch_from_gpu_buffer_3f(index); clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw); clip.radii = texels[1]; clip.mode = texels[2].x; #else - vec4 texels[4] = fetch_from_gpu_buffer_4(index); + vec4 texels[4] = fetch_from_gpu_buffer_4f(index); clip.rect = RectWithEndpoint(texels[0].xy, texels[0].zw); clip.radii_top = texels[1]; clip.radii_bottom = texels[2]; diff --git a/gfx/wr/webrender/res/ps_quad_textured.glsl b/gfx/wr/webrender/res/ps_quad_textured.glsl index 48579eb4fe..2382623cdb 100644 --- a/gfx/wr/webrender/res/ps_quad_textured.glsl +++ b/gfx/wr/webrender/res/ps_quad_textured.glsl @@ -2,6 +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/. */ +/// This shader renders solid colors or simple images in a color or alpha target. + #include ps_quad #ifndef SWGL_ANTIALIAS diff --git a/gfx/wr/webrender/res/ps_text_run.glsl b/gfx/wr/webrender/res/ps_text_run.glsl index aabc1e9d8a..9faac99620 100644 --- a/gfx/wr/webrender/res/ps_text_run.glsl +++ b/gfx/wr/webrender/res/ps_text_run.glsl @@ -100,7 +100,7 @@ void main() { PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address); Transform transform = fetch_transform(ph.transform_id); ClipArea clip_area = fetch_clip_area(instance.clip_address); - PictureTask task = fetch_picture_task(instance.picture_task_address); + PictureTask task = fetch_picture_task(ph.picture_task_address); int glyph_index = instance.segment_index; int subpx_dir = (instance.flags >> 8) & 0xff; diff --git a/gfx/wr/webrender/res/render_task.glsl b/gfx/wr/webrender/res/render_task.glsl index cd9aea402c..e5d0c298cd 100644 --- a/gfx/wr/webrender/res/render_task.glsl +++ b/gfx/wr/webrender/res/render_task.glsl @@ -73,7 +73,7 @@ PictureTask fetch_picture_task(int address) { return task; } -#define CLIP_TASK_EMPTY 0x7FFF +#define CLIP_TASK_EMPTY 0x7FFFFFFF struct ClipArea { RectWithEndpoint task_rect; @@ -82,21 +82,22 @@ struct ClipArea { }; ClipArea fetch_clip_area(int index) { - ClipArea area; - + RenderTaskData task_data; if (index >= CLIP_TASK_EMPTY) { - area.task_rect = RectWithEndpoint(vec2(0.0), vec2(0.0)); - area.device_pixel_scale = 0.0; - area.screen_origin = vec2(0.0); + // We deliberately create a dummy RenderTaskData here then convert to a + // ClipArea after this if-else statement, rather than initialize the + // ClipArea in separate branches, to avoid a miscompile in some Adreno + // drivers. See bug 1884791. Unfortunately the specific details of the bug + // are unknown, so please take extra care not to regress this when + // refactoring. + task_data = RenderTaskData(RectWithEndpoint(vec2(0.0), vec2(0.0)), + vec4(0.0)); } else { - RenderTaskData task_data = fetch_render_task_data(index); - - area.task_rect = task_data.task_rect; - area.device_pixel_scale = task_data.user_data.x; - area.screen_origin = task_data.user_data.yz; + task_data = fetch_render_task_data(index); } - return area; + return ClipArea(task_data.task_rect, task_data.user_data.x, + task_data.user_data.yz); } #endif //WR_VERTEX_SHADER diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs index f39b60acc6..605283c58d 100644 --- a/gfx/wr/webrender/src/batch.rs +++ b/gfx/wr/webrender/src/batch.rs @@ -16,7 +16,7 @@ use crate::gpu_types::{SplitCompositeInstance, QuadInstance}; use crate::gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance}; use crate::gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette}; use crate::gpu_types::{ImageBrushData, get_shader_opacity, BoxShadowData, MaskInstance}; -use crate::gpu_types::{ClipMaskInstanceCommon, ClipMaskInstanceImage, ClipMaskInstanceRect, ClipMaskInstanceBoxShadow}; +use crate::gpu_types::{ClipMaskInstanceCommon, ClipMaskInstanceRect, ClipMaskInstanceBoxShadow}; use crate::internal_types::{FastHashMap, Swizzle, TextureSource, Filter}; use crate::picture::{Picture3DContext, PictureCompositeMode, calculate_screen_uv}; use crate::prim_store::{PrimitiveInstanceKind, ClipData}; @@ -26,8 +26,8 @@ use crate::prim_store::{VECS_PER_SEGMENT, PrimitiveInstanceIndex}; use crate::render_target::RenderTargetContext; use crate::render_task_graph::{RenderTaskId, RenderTaskGraph}; use crate::render_task::{RenderTaskAddress, RenderTaskKind, SubPass}; -use crate::renderer::{BlendMode, ShaderColorMode}; -use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH, GpuBufferBuilder, GpuBufferAddress}; +use crate::renderer::{BlendMode, GpuBufferBuilder, ShaderColorMode}; +use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH, GpuBufferAddress}; use crate::resource_cache::{GlyphFetchResult, ImageProperties}; use crate::space::SpaceMapper; use crate::visibility::{PrimitiveVisibilityFlags, VisibilityState}; @@ -38,7 +38,7 @@ use crate::segment::EdgeAaSegmentMask; // Special sentinel value recognized by the shader. It is considered to be // a dummy task that doesn't mask out anything. -const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fff); +const OPAQUE_TASK_ADDRESS: RenderTaskAddress = RenderTaskAddress(0x7fffffff); /// Used to signal there are no segments provided with this primitive. pub const INVALID_SEGMENT_INDEX: i32 = 0xffff; @@ -745,13 +745,10 @@ impl BatchBuilder { prim_header_index: PrimitiveHeaderIndex, resource_address: i32, ) { - let render_task_address = self.batcher.render_task_address; - let instance = BrushInstance { segment_index, edge_flags, clip_task_address, - render_task_address, brush_flags, prim_header_index, resource_address, @@ -803,7 +800,7 @@ impl BatchBuilder { &mut self, prim_instance_index: PrimitiveInstanceIndex, transform_id: TransformPaletteId, - gpu_buffer_address: GpuBufferAddress, + prim_address_f: GpuBufferAddress, quad_flags: QuadFlags, edge_flags: EdgeAaSegmentMask, segment_index: u8, @@ -811,6 +808,7 @@ impl BatchBuilder { z_generator: &mut ZBufferIdGenerator, prim_instances: &[PrimitiveInstance], render_tasks: &RenderTaskGraph, + gpu_buffer_builder: &mut GpuBufferBuilder, ) { let prim_instance = &prim_instances[prim_instance_index.0 as usize]; let prim_info = &prim_instance.vis; @@ -820,13 +818,14 @@ impl BatchBuilder { add_quad_to_batch( self.batcher.render_task_address, transform_id, - gpu_buffer_address, + prim_address_f, quad_flags, edge_flags, segment_index, task_id, z_id, render_tasks, + gpu_buffer_builder, |key, instance| { let batch = self.batcher.set_params_and_get_batch( key, @@ -857,7 +856,7 @@ impl BatchBuilder { surface_spatial_node_index: SpatialNodeIndex, z_generator: &mut ZBufferIdGenerator, prim_instances: &[PrimitiveInstance], - _gpu_buffer_builder: &mut GpuBufferBuilder, + gpu_buffer_builder: &mut GpuBufferBuilder, segments: &[RenderTaskId], ) { let (prim_instance_index, extra_prim_gpu_address) = match cmd { @@ -883,6 +882,7 @@ impl BatchBuilder { z_generator, prim_instances, render_tasks, + gpu_buffer_builder, ); } else { for (i, task_id) in segments.iter().enumerate() { @@ -900,6 +900,7 @@ impl BatchBuilder { z_generator, prim_instances, render_tasks, + gpu_buffer_builder, ); } } @@ -1005,6 +1006,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, [get_shader_opacity(1.0), 0, 0, 0], ); @@ -1083,6 +1085,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -1137,6 +1140,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, [ (run.raster_scale * 65535.0).round() as i32, 0, @@ -1312,7 +1316,6 @@ impl BatchBuilder { let key = BatchKey::new(kind, blend_mode, textures); - let render_task_address = batcher.render_task_address; let batch = batcher.alpha_batch_list.set_params_and_get_batch( key, batch_features, @@ -1323,7 +1326,6 @@ impl BatchBuilder { batch.reserve(glyphs.len()); for glyph in glyphs { batch.push(base_instance.build( - render_task_address, clip_task_address, subpx_dir, glyph.index_in_text_run, @@ -1397,6 +1399,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, prim_user_data, ); @@ -1531,6 +1534,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, ImageBrushData { color_mode: ShaderColorMode::Image, alpha_type: AlphaType::PremultipliedAlpha, @@ -1616,6 +1620,7 @@ impl BatchBuilder { let shadow_prim_header_index = prim_headers.push( &shadow_prim_header, z_id, + self.batcher.render_task_address, ImageBrushData { color_mode: ShaderColorMode::Alpha, alpha_type: AlphaType::PremultipliedAlpha, @@ -1642,6 +1647,7 @@ impl BatchBuilder { let content_prim_header_index = prim_headers.push( &prim_header, z_id_content, + self.batcher.render_task_address, ImageBrushData { color_mode: ShaderColorMode::Image, alpha_type: AlphaType::PremultipliedAlpha, @@ -1687,12 +1693,17 @@ impl BatchBuilder { textures, ); - let prim_header_index = prim_headers.push(&prim_header, z_id, [ - uv_rect_address.as_int(), - amount, - 0, - 0, - ]); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + [ + uv_rect_address.as_int(), + amount, + 0, + 0, + ] + ); self.add_brush_instance_to_batches( key, @@ -1771,12 +1782,17 @@ impl BatchBuilder { textures, ); - let prim_header_index = prim_headers.push(&prim_header, z_id, [ - uv_rect_address.as_int(), - filter_mode, - user_data, - 0, - ]); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + [ + uv_rect_address.as_int(), + filter_mode, + user_data, + 0, + ] + ); self.add_brush_instance_to_batches( key, @@ -1826,12 +1842,17 @@ impl BatchBuilder { textures, ); - let prim_header_index = prim_headers.push(&prim_header, z_id, [ - uv_rect_address.as_int(), - filter_mode, - user_data, - 0, - ]); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + [ + uv_rect_address.as_int(), + filter_mode, + user_data, + 0, + ] + ); self.add_brush_instance_to_batches( key, @@ -1882,6 +1903,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, ImageBrushData { color_mode: match key.blend_mode { BlendMode::MultiplyDualSource => ShaderColorMode::MultiplyDualSource, @@ -1924,8 +1946,6 @@ impl BatchBuilder { // and allow mix-blends to operate on picture cache surfaces without // a separate isolated intermediate surface. - let render_task_address = self.batcher.render_task_address; - let batch_key = BatchKey::new( BatchKind::Brush( BrushBatchKind::MixBlend { @@ -1953,18 +1973,22 @@ impl BatchBuilder { ); let src_uv_address = render_tasks[pic_task_id].get_texture_address(gpu_cache); let readback_uv_address = render_tasks[backdrop_id].get_texture_address(gpu_cache); - let prim_header_index = prim_headers.push(&prim_header, z_id, [ - mode as u32 as i32, - readback_uv_address.as_int(), - src_uv_address.as_int(), - 0, - ]); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + [ + mode as u32 as i32, + readback_uv_address.as_int(), + src_uv_address.as_int(), + 0, + ] + ); let instance = BrushInstance { segment_index: INVALID_SEGMENT_INDEX, edge_flags: EdgeAaSegmentMask::all(), clip_task_address, - render_task_address, brush_flags, prim_header_index, resource_address: 0, @@ -2030,12 +2054,17 @@ impl BatchBuilder { // by this inner loop. let z_id = z_generator.next(); - let prim_header_index = prim_headers.push(&prim_header, z_id, [ - uv_rect_address.as_int(), - BrushFlags::PERSPECTIVE_INTERPOLATION.bits() as i32, - 0, - child_clip_task_address.0 as i32, - ]); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + [ + uv_rect_address.as_int(), + BrushFlags::PERSPECTIVE_INTERPOLATION.bits() as i32, + 0, + child_clip_task_address.0 as i32, + ] + ); let key = BatchKey::new( BatchKind::SplitComposite, @@ -2088,6 +2117,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2141,6 +2171,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, ImageBrushData { color_mode: ShaderColorMode::Image, alpha_type: AlphaType::PremultipliedAlpha, @@ -2215,6 +2246,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2274,6 +2306,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2394,6 +2427,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2498,6 +2532,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2547,7 +2582,12 @@ impl BatchBuilder { specific_prim_address: gpu_cache.get_address(&gpu_handle), transform_id, }; - let prim_header_index = prim_headers.push(&prim_header, z_id, prim_user_data); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + prim_user_data, + ); for (i, tile) in chunk.iter().enumerate() { let (uv_rect_address, texture) = match render_tasks.resolve_location(tile.src_color, gpu_cache) { @@ -2616,7 +2656,12 @@ impl BatchBuilder { prim_header.specific_prim_address = gpu_cache.get_address(&prim_data.gpu_cache_handle); - let prim_header_index = prim_headers.push(&prim_header, z_id, user_data); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + self.batcher.render_task_address, + user_data, + ); let segments = if prim_data.brush_segments.is_empty() { None @@ -2660,7 +2705,12 @@ impl BatchBuilder { local_clip_rect: tile.local_clip_rect, ..prim_header }; - let prim_header_index = prim_headers.push(&tile_prim_header, z_id, user_data); + let prim_header_index = prim_headers.push( + &tile_prim_header, + z_id, + self.batcher.render_task_address, + user_data, + ); self.add_brush_instance_to_batches( key, @@ -2735,6 +2785,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2777,7 +2828,12 @@ impl BatchBuilder { local_clip_rect: tile.local_clip_rect, ..prim_header }; - let prim_header_index = prim_headers.push(&tile_prim_header, z_id, prim_user_data); + let prim_header_index = prim_headers.push( + &tile_prim_header, + z_id, + self.batcher.render_task_address, + prim_user_data, + ); self.add_brush_instance_to_batches( batch_key, @@ -2853,6 +2909,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -2895,7 +2952,12 @@ impl BatchBuilder { local_clip_rect: tile.local_clip_rect, ..prim_header }; - let prim_header_index = prim_headers.push(&tile_prim_header, z_id, prim_user_data); + let prim_header_index = prim_headers.push( + &tile_prim_header, + z_id, + self.batcher.render_task_address, + prim_user_data, + ); self.add_brush_instance_to_batches( batch_key, @@ -2972,6 +3034,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, batch_params.prim_user_data, ); @@ -3014,7 +3077,12 @@ impl BatchBuilder { local_clip_rect: tile.local_clip_rect, ..prim_header }; - let prim_header_index = prim_headers.push(&tile_prim_header, z_id, prim_user_data); + let prim_header_index = prim_headers.push( + &tile_prim_header, + z_id, + self.batcher.render_task_address, + prim_user_data, + ); self.add_brush_instance_to_batches( batch_key, @@ -3068,6 +3136,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, ImageBrushData { color_mode: ShaderColorMode::Image, alpha_type: AlphaType::PremultipliedAlpha, @@ -3179,6 +3248,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push( &prim_header, z_id, + self.batcher.render_task_address, [get_shader_opacity(1.0), 0, 0, 0], ); @@ -3477,8 +3547,6 @@ pub struct ClipBatchList { /// Rectangle draws fill up the rectangles with rounded corners. pub slow_rectangles: Vec, pub fast_rectangles: Vec, - /// Image draws apply the image masking. - pub images: FastHashMap<(TextureSource, Option), Vec>, pub box_shadows: FastHashMap>, } @@ -3487,7 +3555,6 @@ impl ClipBatchList { ClipBatchList { slow_rectangles: Vec::new(), fast_rectangles: Vec::new(), - images: FastHashMap::default(), box_shadows: FastHashMap::default(), } } @@ -3674,20 +3741,11 @@ impl ClipBatcher { ctx.spatial_tree, ); - // For clip mask images, we need to map from the primitive's layout space to - // the target space, as the cs_clip_image shader needs to forward transform - // the local image bounds, rather than backwards transform the target bounds - // as in done in write_clip_tile_vertex. - let prim_transform_id = match clip_node.item.kind { - ClipItemKind::Image { .. } => { panic!("bug: old path not supported") } - _ => { - transforms.get_id( - root_spatial_node_index, - ctx.root_spatial_node_index, - ctx.spatial_tree, - ) - } - }; + let prim_transform_id = transforms.get_id( + root_spatial_node_index, + ctx.root_spatial_node_index, + ctx.spatial_tree, + ); let common = ClipMaskInstanceCommon { sub_rect: DeviceRect::from_size(actual_rect.size()), @@ -3837,13 +3895,14 @@ impl<'a, 'rc> RenderTargetContext<'a, 'rc> { pub fn add_quad_to_batch( render_task_address: RenderTaskAddress, transform_id: TransformPaletteId, - gpu_buffer_address: GpuBufferAddress, + prim_address_f: GpuBufferAddress, quad_flags: QuadFlags, edge_flags: EdgeAaSegmentMask, segment_index: u8, task_id: RenderTaskId, z_id: ZBufferId, render_tasks: &RenderTaskGraph, + gpu_buffer_builder: &mut GpuBufferBuilder, mut f: F, ) where F: FnMut(BatchKey, PrimitiveInstanceData) { @@ -3857,6 +3916,15 @@ pub fn add_quad_to_batch( All = 5, } + let mut writer = gpu_buffer_builder.i32.write_blocks(1); + writer.push_one([ + transform_id.0 as i32, + z_id.0, + 0, + 0, + ]); + let prim_address_i = writer.finish(); + let texture = match task_id { RenderTaskId::INVALID => { TextureSource::Invalid @@ -3898,7 +3966,8 @@ pub fn add_quad_to_batch( if edge_flags.is_empty() { let instance = QuadInstance { render_task_address, - prim_address: gpu_buffer_address, + prim_address_i, + prim_address_f, z_id, transform_id, edge_flags: edge_flags_bits, @@ -3911,7 +3980,8 @@ pub fn add_quad_to_batch( } else if quad_flags.contains(QuadFlags::USE_AA_SEGMENTS) { let main_instance = QuadInstance { render_task_address, - prim_address: gpu_buffer_address, + prim_address_i, + prim_address_f, z_id, transform_id, edge_flags: edge_flags_bits, @@ -3956,7 +4026,8 @@ pub fn add_quad_to_batch( } else { let instance = QuadInstance { render_task_address, - prim_address: gpu_buffer_address, + prim_address_i, + prim_address_f, z_id, transform_id, edge_flags: edge_flags_bits, diff --git a/gfx/wr/webrender/src/device/gl.rs b/gfx/wr/webrender/src/device/gl.rs index 5ad9469185..04a7e13023 100644 --- a/gfx/wr/webrender/src/device/gl.rs +++ b/gfx/wr/webrender/src/device/gl.rs @@ -138,9 +138,13 @@ pub enum UploadMethod { } /// Plain old data that can be used to initialize a texture. -pub unsafe trait Texel: Copy {} -unsafe impl Texel for u8 {} -unsafe impl Texel for f32 {} +pub unsafe trait Texel: Copy + Default { + fn image_format() -> ImageFormat; +} + +unsafe impl Texel for u8 { + fn image_format() -> ImageFormat { ImageFormat::R8 } +} /// Returns the size in bytes of a depth target with the given dimensions. fn depth_target_size_in_bytes(dimensions: &DeviceIntSize) -> usize { diff --git a/gfx/wr/webrender/src/frame_builder.rs b/gfx/wr/webrender/src/frame_builder.rs index 4ff798c103..b975c960eb 100644 --- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -25,7 +25,7 @@ use crate::prim_store::{PictureIndex, PrimitiveScratchBuffer}; use crate::prim_store::{DeferredResolve, PrimitiveInstance}; use crate::profiler::{self, TransactionProfile}; use crate::render_backend::{DataStores, ScratchBuffer}; -use crate::renderer::{GpuBuffer, GpuBufferBuilder}; +use crate::renderer::{GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI, GpuBufferBuilder}; use crate::render_target::{RenderTarget, PictureCacheTarget, TextureCacheRenderTarget, PictureCacheTargetKind}; use crate::render_target::{RenderTargetContext, RenderTargetKind, AlphaRenderTarget, ColorRenderTarget}; use crate::render_task_graph::{RenderTaskGraph, Pass, SubPassSurface}; @@ -558,7 +558,10 @@ impl FrameBuilder { let mut cmd_buffers = CommandBufferList::new(); // TODO(gw): Recycle backing vec buffers for gpu buffer builder between frames - let mut gpu_buffer_builder = GpuBufferBuilder::new(); + let mut gpu_buffer_builder = GpuBufferBuilder { + f32: GpuBufferBuilderF::new(), + i32: GpuBufferBuilderI::new(), + }; self.build_layer_screen_rects_and_cull_layers( scene, @@ -690,7 +693,8 @@ impl FrameBuilder { scene.clip_store.end_frame(&mut scratch.clip_store); scratch.end_frame(); - let gpu_buffer = gpu_buffer_builder.finalize(&render_tasks); + let gpu_buffer_f = gpu_buffer_builder.f32.finalize(&render_tasks); + let gpu_buffer_i = gpu_buffer_builder.i32.finalize(&render_tasks); Frame { device_rect: DeviceIntRect::from_origin_and_size( @@ -707,7 +711,8 @@ impl FrameBuilder { prim_headers, debug_items: mem::replace(&mut scratch.primitive.debug_items, Vec::new()), composite_state, - gpu_buffer, + gpu_buffer_f, + gpu_buffer_i, } } @@ -759,7 +764,6 @@ impl FrameBuilder { const LAYOUT_PORT_COLOR: ColorF = debug_colors::RED; const VISUAL_PORT_COLOR: ColorF = debug_colors::BLUE; const DISPLAYPORT_COLOR: ColorF = debug_colors::LIME; - const NOTHING: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 }; let viewport = scroll_frame_info.viewport_rect; @@ -805,9 +809,10 @@ impl FrameBuilder { } let mut add_rect = |rect, border, fill| -> Option<()> { + const STROKE_WIDTH: f32 = 2.0; // Place rect in scroll frame's local coordinate space let transformed_rect = transform.outer_transformed_box2d(&rect)?; - + // Transform to world coordinates, using root-content coords as an intermediate step. let mut root_content_rect = local_to_root_content.outer_transformed_box2d(&transformed_rect)?; // In root-content coords, apply the root content node's viewport clip. @@ -820,21 +825,28 @@ impl FrameBuilder { } let world_rect = root_content_to_world.outer_transformed_box2d(&root_content_rect)?; + scratch.push_debug_rect_with_stroke_width(world_rect, border, STROKE_WIDTH); + // Add world coordinate rects to scratch.debug_items - // TODO: Add a parameter to control the border thickness of the rects, and make them a bit thicker. - scratch.push_debug_rect(world_rect * DevicePixelScale::new(1.0), border, fill); + if let Some(fill_color) = fill { + let interior_world_rect = WorldRect::new( + world_rect.min + WorldVector2D::new(STROKE_WIDTH, STROKE_WIDTH), + world_rect.max - WorldVector2D::new(STROKE_WIDTH, STROKE_WIDTH) + ); + scratch.push_debug_rect(interior_world_rect * DevicePixelScale::new(1.0), border, fill_color); + } Some(()) }; - add_rect(minimap_data.scrollable_rect, PAGE_BORDER_COLOR, BACKGROUND_COLOR); - add_rect(minimap_data.visual_viewport, VISUAL_PORT_COLOR, NOTHING); - add_rect(minimap_data.displayport, DISPLAYPORT_COLOR, DISPLAYPORT_BACKGROUND_COLOR); + add_rect(minimap_data.scrollable_rect, PAGE_BORDER_COLOR, Some(BACKGROUND_COLOR)); + add_rect(minimap_data.displayport, DISPLAYPORT_COLOR, Some(DISPLAYPORT_BACKGROUND_COLOR)); // Only render a distinct layout viewport for the root content. // For other scroll frames, the visual and layout viewports coincide. if minimap_data.is_root_content { - add_rect(minimap_data.layout_viewport, LAYOUT_PORT_COLOR, NOTHING); + add_rect(minimap_data.layout_viewport, LAYOUT_PORT_COLOR, None); } + add_rect(minimap_data.visual_viewport, VISUAL_PORT_COLOR, None); } } }); @@ -967,7 +979,6 @@ pub fn build_render_pass( let task_id = sub_pass.task_ids[0]; let task = &render_tasks[task_id]; let target_rect = task.get_target_rect(); - let mut gpu_buffer_builder = GpuBufferBuilder::new(); match task.kind { RenderTaskKind::Picture(ref pic_task) => { @@ -998,7 +1009,7 @@ pub fn build_render_pass( pic_task.surface_spatial_node_index, z_generator, prim_instances, - &mut gpu_buffer_builder, + gpu_buffer_builder, segments, ); }); @@ -1072,6 +1083,7 @@ pub fn build_render_pass( z_generator, prim_instances, cmd_buffers, + gpu_buffer_builder, ); pass.alpha.build( ctx, @@ -1082,6 +1094,7 @@ pub fn build_render_pass( z_generator, prim_instances, cmd_buffers, + gpu_buffer_builder, ); pass @@ -1127,7 +1140,8 @@ pub struct Frame { /// Main GPU data buffer constructed (primarily) during the prepare /// pass for primitives that were visible and dirty. - pub gpu_buffer: GpuBuffer, + pub gpu_buffer_f: GpuBufferF, + pub gpu_buffer_i: GpuBufferI, } impl Frame { diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs index f6d24b2e39..e222ebed04 100644 --- a/gfx/wr/webrender/src/gpu_types.rs +++ b/gfx/wr/webrender/src/gpu_types.rs @@ -125,6 +125,7 @@ pub struct SvgFilterInstance { pub kind: u16, pub input_count: u16, pub generic_int: u16, + pub padding: u16, pub extra_data_address: GpuCacheAddress, } @@ -171,17 +172,6 @@ pub struct ClipMaskInstanceCommon { pub prim_transform_id: TransformPaletteId, } -#[derive(Clone, Debug)] -#[cfg_attr(feature = "capture", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -#[repr(C)] -pub struct ClipMaskInstanceImage { - pub common: ClipMaskInstanceCommon, - pub tile_rect: LayoutRect, - pub resource_address: GpuCacheAddress, - pub local_rect: LayoutRect, -} - #[derive(Clone, Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] @@ -428,6 +418,7 @@ impl PrimitiveHeaders { &mut self, prim_header: &PrimitiveHeader, z: ZBufferId, + render_task_address: RenderTaskAddress, user_data: [i32; 4], ) -> PrimitiveHeaderIndex { debug_assert_eq!(self.headers_int.len(), self.headers_float.len()); @@ -440,7 +431,7 @@ impl PrimitiveHeaders { self.headers_int.push(PrimitiveHeaderI { z, - unused: 0, + render_task_address, specific_prim_address: prim_header.specific_prim_address.as_int(), transform_id: prim_header.transform_id, user_data, @@ -480,7 +471,7 @@ pub struct PrimitiveHeaderI { pub z: ZBufferId, pub specific_prim_address: i32, pub transform_id: TransformPaletteId, - pub unused: i32, // To ensure required 16 byte alignment of vertex textures + pub render_task_address: RenderTaskAddress, pub user_data: [i32; 4], } @@ -501,7 +492,6 @@ impl GlyphInstance { // header since they are constant, and some can be // compressed to a smaller size. pub fn build(&self, - render_task: RenderTaskAddress, clip_task: RenderTaskAddress, subpx_dir: SubpixelDirection, glyph_index_in_text_run: i32, @@ -511,8 +501,7 @@ impl GlyphInstance { PrimitiveInstanceData { data: [ self.prim_header_index.0 as i32, - ((render_task.0 as i32) << 16) - | clip_task.0 as i32, + clip_task.0 as i32, (subpx_dir as u32 as i32) << 24 | (color_mode as u32 as i32) << 16 | glyph_index_in_text_run, @@ -536,7 +525,7 @@ impl From for PrimitiveInstanceData { instance.prim_header_index.0, instance.polygons_address, instance.z.0, - instance.render_task_address.0 as i32, + instance.render_task_address.0, ], } } @@ -547,7 +536,8 @@ impl From for PrimitiveInstanceData { #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct QuadInstance { pub render_task_address: RenderTaskAddress, - pub prim_address: GpuBufferAddress, + pub prim_address_i: GpuBufferAddress, + pub prim_address_f: GpuBufferAddress, pub z_id: ZBufferId, pub transform_id: TransformPaletteId, pub quad_flags: u8, @@ -559,19 +549,23 @@ pub struct QuadInstance { impl From for PrimitiveInstanceData { fn from(instance: QuadInstance) -> Self { /* - [32 bits prim address] - [8 bits quad flags] [8 bits edge flags] [16 bits render task address] - [8 bits segment flags] [24 bits z_id] - [8 bits segment index] [24 bits xf_id] - */ + [32 prim address_i] + [32 prim address_f] + [8888 qf ef pi si] + [32 render task address] + */ + PrimitiveInstanceData { data: [ - instance.prim_address.as_int(), - ((instance.quad_flags as i32) << 24) | - ((instance.edge_flags as i32) << 16) | - instance.render_task_address.0 as i32, - ((instance.part_index as i32) << 24) | instance.z_id.0, - ((instance.segment_index as i32) << 24) | instance.transform_id.0 as i32, + instance.prim_address_i.as_int(), + instance.prim_address_f.as_int(), + + ((instance.quad_flags as i32) << 24) | + ((instance.edge_flags as i32) << 16) | + ((instance.part_index as i32) << 8) | + ((instance.segment_index as i32) << 0), + + instance.render_task_address.0, ], } } @@ -659,7 +653,6 @@ impl core::fmt::Debug for BrushFlags { /// Convenience structure to encode into PrimitiveInstanceData. pub struct BrushInstance { pub prim_header_index: PrimitiveHeaderIndex, - pub render_task_address: RenderTaskAddress, pub clip_task_address: RenderTaskAddress, pub segment_index: i32, pub edge_flags: EdgeAaSegmentMask, @@ -672,8 +665,7 @@ impl From for PrimitiveInstanceData { PrimitiveInstanceData { data: [ instance.prim_header_index.0, - ((instance.render_task_address.0 as i32) << 16) - | instance.clip_task_address.0 as i32, + instance.clip_task_address.0, instance.segment_index | ((instance.brush_flags.bits() as i32) << 16) | ((instance.edge_flags.bits() as i32) << 28), diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index e8746ad161..1f1fd5e4f6 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -139,11 +139,11 @@ use std::collections::hash_map::Entry; use std::ops::Range; use crate::picture_textures::PictureCacheTextureHandle; use crate::util::{MaxRect, VecHelper, MatrixHelpers, Recycler, ScaleOffset}; -use crate::filterdata::{FilterDataHandle}; +use crate::filterdata::FilterDataHandle; use crate::tile_cache::{SliceDebugInfo, TileDebugInfo, DirtyTileDebugInfo}; use crate::visibility::{PrimitiveVisibilityFlags, FrameVisibilityContext}; use crate::visibility::{VisibilityState, FrameVisibilityState}; -use crate::scene_building::{SliceFlags}; +use crate::scene_building::SliceFlags; // Maximum blur radius for blur filter (different than box-shadow blur). // Taken from FilterNodeSoftware.cpp in Gecko. @@ -3951,7 +3951,7 @@ impl SurfaceInfo { &self, local_rect: &PictureRect, spatial_tree: &SpatialTree, - ) -> Option { + ) -> Option { let local_rect = match local_rect.intersection(&self.clipping_rect) { Some(rect) => rect, None => return None, @@ -3969,10 +3969,21 @@ impl SurfaceInfo { local_to_world.map(&local_rect).unwrap() } else { + // The content should have been culled out earlier. + assert!(self.device_pixel_scale.0 > 0.0); + local_rect.cast_unit() }; - Some((raster_rect * self.device_pixel_scale).round_out()) + let surface_rect = (raster_rect * self.device_pixel_scale).round_out().to_i32(); + if surface_rect.is_empty() { + // The local_rect computed above may have non-empty size that is very + // close to zero. Due to limited arithmetic precision, the SpaceMapper + // might transform the near-zero-sized rect into a zero-sized one. + return None; + } + + Some(surface_rect) } } @@ -5014,7 +5025,7 @@ impl PicturePrimitive { let content_device_rect = content_device_rect .intersection(&max_content_rect) - .expect("bug: no intersection with tile dirty rect"); + .expect("bug: no intersection with tile dirty rect: {content_device_rect:?} / {max_content_rect:?}"); let content_task_size = content_device_rect.size(); let normalized_content_rect = content_task_size.into(); @@ -6128,22 +6139,28 @@ impl PicturePrimitive { PictureCompositeMode::TileCache { slice_id } => { let tile_cache = tile_caches.get_mut(&slice_id).unwrap(); - // We only update the raster scale if we're in high quality zoom mode, or there is no - // pinch-zoom active. This means that in low quality pinch-zoom, we retain the initial - // scale factor until the zoom ends, then select a high quality zoom factor for the next - // frame to be drawn. - let update_raster_scale = - !frame_context.fb_config.low_quality_pinch_zoom || - !frame_context.spatial_tree.get_spatial_node(tile_cache.spatial_node_index).is_ancestor_or_self_zooming; - - if update_raster_scale { - // Get the complete scale-offset from local space to device space - let local_to_device = get_relative_scale_offset( - tile_cache.spatial_node_index, - frame_context.root_spatial_node_index, - frame_context.spatial_tree, - ); + // Get the complete scale-offset from local space to device space + let local_to_device = get_relative_scale_offset( + tile_cache.spatial_node_index, + frame_context.root_spatial_node_index, + frame_context.spatial_tree, + ); + let local_to_cur_raster_scale = local_to_device.scale.x / tile_cache.current_raster_scale; + // We only update the raster scale if we're in high quality zoom mode, or there is no + // pinch-zoom active, or the zoom has doubled or halved since the raster scale was + // last updated. During a low-quality zoom we therefore typically retain the previous + // scale factor, which avoids expensive re-rasterizations, except for when the zoom + // has become too large or too small when we re-rasterize to avoid bluriness or a + // proliferation of picture cache tiles. When the zoom ends we select a high quality + // scale factor for the next frame to be drawn. + if !frame_context.fb_config.low_quality_pinch_zoom + || !frame_context + .spatial_tree.get_spatial_node(tile_cache.spatial_node_index) + .is_ancestor_or_self_zooming + || local_to_cur_raster_scale <= 0.5 + || local_to_cur_raster_scale >= 2.0 + { tile_cache.current_raster_scale = local_to_device.scale.x; } diff --git a/gfx/wr/webrender/src/prepare.rs b/gfx/wr/webrender/src/prepare.rs index f32c94073e..a59eca0670 100644 --- a/gfx/wr/webrender/src/prepare.rs +++ b/gfx/wr/webrender/src/prepare.rs @@ -28,18 +28,18 @@ use crate::prim_store::line_dec::MAX_LINE_DECORATION_RESOLUTION; use crate::prim_store::*; use crate::prim_store::gradient::GradientGpuBlockBuilder; use crate::render_backend::DataStores; -use crate::render_task_graph::{RenderTaskId}; +use crate::render_task_graph::RenderTaskId; use crate::render_task_cache::RenderTaskCacheKeyKind; use crate::render_task_cache::{RenderTaskCacheKey, to_cache_size, RenderTaskParent}; use crate::render_task::{RenderTaskKind, RenderTask, SubPass, MaskSubPass, EmptyTask}; -use crate::renderer::{GpuBufferBuilder, GpuBufferAddress}; +use crate::renderer::{GpuBufferBuilderF, GpuBufferAddress}; use crate::segment::{EdgeAaSegmentMask, SegmentBuilder}; use crate::space::SpaceMapper; use crate::util::{clamp_to_scale_factor, pack_as_float, MaxRect}; use crate::visibility::{compute_conservative_visible_rect, PrimitiveVisibility, VisibilityState}; -const MAX_MASK_SIZE: f32 = 4096.0; +const MAX_MASK_SIZE: i32 = 4096; const MIN_BRUSH_SPLIT_SIZE: f32 = 256.0; const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0; @@ -141,14 +141,32 @@ fn can_use_clip_chain_for_quad_path( true } +/// Describes how clipping affects the rendering of a quad primitive. +/// +/// As a general rule, parts of the quad that require masking are prerendered in an +/// intermediate target and the mask is applied using multiplicative blending to +/// the intermediate result before compositing it into the destination target. +/// +/// Each segment can opt in or out of masking independently. #[derive(Debug, Copy, Clone)] pub enum QuadRenderStrategy { + /// The quad is not affected by any mask and is drawn directly in the destination + /// target. Direct, + /// The quad is drawn entirely in an intermediate target and a mask is applied + /// before compositing in the destination target. Indirect, + /// A rounded rectangle clip is applied to the quad primitive via a nine-patch. + /// The segments of the nine-patch that require a mask are rendered and masked in + /// an intermediate target, while other segments are drawn directly in the destination + /// target. NinePatch { radius: LayoutVector2D, clip_rect: LayoutRect, }, + /// Split the primitive into coarse tiles so that each tile independently + /// has the opportunity to be drawn directly in the destination target or + /// via an intermediate target if it is affected by a mask. Tiled { x_tiles: u16, y_tiles: u16, @@ -163,69 +181,67 @@ fn get_prim_render_strategy( can_use_nine_patch: bool, spatial_tree: &SpatialTree, ) -> QuadRenderStrategy { - if clip_chain.needs_mask { - fn tile_count_for_size(size: f32) -> u16 { - (size / MIN_BRUSH_SPLIT_SIZE).min(4.0).max(1.0).ceil() as u16 - } + if !clip_chain.needs_mask { + return QuadRenderStrategy::Direct + } - let prim_coverage_size = clip_chain.pic_coverage_rect.size(); - let x_tiles = tile_count_for_size(prim_coverage_size.width); - let y_tiles = tile_count_for_size(prim_coverage_size.height); - let try_split_prim = x_tiles > 1 || y_tiles > 1; - - if try_split_prim { - if can_use_nine_patch { - if clip_chain.clips_range.count == 1 { - let clip_instance = clip_store.get_instance_from_range(&clip_chain.clips_range, 0); - let clip_node = &data_stores.clip[clip_instance.handle]; - - if let ClipItemKind::RoundedRectangle { ref radius, mode: ClipMode::Clip, rect, .. } = clip_node.item.kind { - let max_corner_width = radius.top_left.width - .max(radius.bottom_left.width) - .max(radius.top_right.width) - .max(radius.bottom_right.width); - let max_corner_height = radius.top_left.height - .max(radius.bottom_left.height) - .max(radius.top_right.height) - .max(radius.bottom_right.height); - - if max_corner_width <= 0.5 * rect.size().width && - max_corner_height <= 0.5 * rect.size().height { - - let clip_prim_coords_match = spatial_tree.is_matching_coord_system( - prim_spatial_node_index, - clip_node.item.spatial_node_index, - ); + fn tile_count_for_size(size: f32) -> u16 { + (size / MIN_BRUSH_SPLIT_SIZE).min(4.0).max(1.0).ceil() as u16 + } - if clip_prim_coords_match { - let map_clip_to_prim = SpaceMapper::new_with_target( - prim_spatial_node_index, - clip_node.item.spatial_node_index, - LayoutRect::max_rect(), - spatial_tree, - ); + let prim_coverage_size = clip_chain.pic_coverage_rect.size(); + let x_tiles = tile_count_for_size(prim_coverage_size.width); + let y_tiles = tile_count_for_size(prim_coverage_size.height); + let try_split_prim = x_tiles > 1 || y_tiles > 1; - if let Some(rect) = map_clip_to_prim.map(&rect) { - return QuadRenderStrategy::NinePatch { - radius: LayoutVector2D::new(max_corner_width, max_corner_height), - clip_rect: rect, - }; - } - } - } + if !try_split_prim { + return QuadRenderStrategy::Indirect; + } + + if can_use_nine_patch && clip_chain.clips_range.count == 1 { + let clip_instance = clip_store.get_instance_from_range(&clip_chain.clips_range, 0); + let clip_node = &data_stores.clip[clip_instance.handle]; + + if let ClipItemKind::RoundedRectangle { ref radius, mode: ClipMode::Clip, rect, .. } = clip_node.item.kind { + let max_corner_width = radius.top_left.width + .max(radius.bottom_left.width) + .max(radius.top_right.width) + .max(radius.bottom_right.width); + let max_corner_height = radius.top_left.height + .max(radius.bottom_left.height) + .max(radius.top_right.height) + .max(radius.bottom_right.height); + + if max_corner_width <= 0.5 * rect.size().width && + max_corner_height <= 0.5 * rect.size().height { + + let clip_prim_coords_match = spatial_tree.is_matching_coord_system( + prim_spatial_node_index, + clip_node.item.spatial_node_index, + ); + + if clip_prim_coords_match { + let map_clip_to_prim = SpaceMapper::new_with_target( + prim_spatial_node_index, + clip_node.item.spatial_node_index, + LayoutRect::max_rect(), + spatial_tree, + ); + + if let Some(rect) = map_clip_to_prim.map(&rect) { + return QuadRenderStrategy::NinePatch { + radius: LayoutVector2D::new(max_corner_width, max_corner_height), + clip_rect: rect, + }; } } } - - QuadRenderStrategy::Tiled { - x_tiles, - y_tiles, - } - } else { - QuadRenderStrategy::Indirect } - } else { - QuadRenderStrategy::Direct + } + + QuadRenderStrategy::Tiled { + x_tiles, + y_tiles, } } @@ -452,7 +468,7 @@ fn prepare_interned_prim_for_render( kind: RenderTaskCacheKeyKind::LineDecoration(cache_key.clone()), }, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, false, @@ -607,7 +623,7 @@ fn prepare_interned_prim_for_render( handles.push(frame_state.resource_cache.request_render_task( cache_key, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, false, // TODO(gw): We don't calculate opacity for borders yet! @@ -764,7 +780,7 @@ fn prepare_interned_prim_for_render( // the written block count) to gpu-buffer, we could add a trait for // writing typed data? let main_prim_address = write_prim_blocks( - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, prim_data.common.prim_rect, prim_instance.vis.clip_chain.local_clip_rect, premul_color, @@ -787,24 +803,21 @@ fn prepare_interned_prim_for_render( } QuadRenderStrategy::Indirect => { let surface = &frame_state.surfaces[pic_context.surface_index.0]; - let clipped_surface_rect = surface.get_surface_rect( + let Some(clipped_surface_rect) = surface.get_surface_rect( &prim_instance.vis.clip_chain.pic_coverage_rect, frame_context.spatial_tree, - ).expect("bug: what can cause this?"); - - let p0 = clipped_surface_rect.min.floor(); - let p1 = clipped_surface_rect.max.ceil(); + ) else { + return; + }; - let x0 = p0.x; - let y0 = p0.y; - let x1 = p1.x; - let y1 = p1.y; + let p0 = clipped_surface_rect.min.to_f32(); + let p1 = clipped_surface_rect.max.to_f32(); let segment = add_segment( - x0, - y0, - x1, - y1, + p0.x, + p0.y, + p1.x, + p1.y, true, prim_instance, prim_spatial_node_index, @@ -820,7 +833,7 @@ fn prepare_interned_prim_for_render( add_composite_prim( prim_instance_index, - LayoutRect::new(LayoutPoint::new(x0, y0), LayoutPoint::new(x1, y1)), + LayoutRect::new(p0.cast_unit(), p1.cast_unit()), premul_color, quad_flags, frame_state, @@ -831,10 +844,12 @@ fn prepare_interned_prim_for_render( QuadRenderStrategy::Tiled { x_tiles, y_tiles } => { let surface = &frame_state.surfaces[pic_context.surface_index.0]; - let clipped_surface_rect = surface.get_surface_rect( + let Some(clipped_surface_rect) = surface.get_surface_rect( &prim_instance.vis.clip_chain.pic_coverage_rect, frame_context.spatial_tree, - ).expect("bug: what can cause this?"); + ) else { + return; + }; let unclipped_surface_rect = surface.map_to_device_rect( &prim_instance.vis.clip_chain.pic_coverage_rect, @@ -843,21 +858,21 @@ fn prepare_interned_prim_for_render( scratch.quad_segments.clear(); - let mut x_coords = vec![clipped_surface_rect.min.x.round()]; - let mut y_coords = vec![clipped_surface_rect.min.y.round()]; + let mut x_coords = vec![clipped_surface_rect.min.x]; + let mut y_coords = vec![clipped_surface_rect.min.y]; - let dx = (clipped_surface_rect.max.x - clipped_surface_rect.min.x) / x_tiles as f32; - let dy = (clipped_surface_rect.max.y - clipped_surface_rect.min.y) / y_tiles as f32; + let dx = (clipped_surface_rect.max.x - clipped_surface_rect.min.x) as f32 / x_tiles as f32; + let dy = (clipped_surface_rect.max.y - clipped_surface_rect.min.y) as f32 / y_tiles as f32; - for x in 1 .. x_tiles { - x_coords.push((clipped_surface_rect.min.x + x as f32 * dx).round()); + for x in 1 .. (x_tiles as i32) { + x_coords.push((clipped_surface_rect.min.x as f32 + x as f32 * dx).round() as i32); } - for y in 1 .. y_tiles { - y_coords.push((clipped_surface_rect.min.y + y as f32 * dy).round()); + for y in 1 .. (y_tiles as i32) { + y_coords.push((clipped_surface_rect.min.y as f32 + y as f32 * dy).round() as i32); } - x_coords.push(clipped_surface_rect.max.x.round()); - y_coords.push(clipped_surface_rect.max.y.round()); + x_coords.push(clipped_surface_rect.max.x); + y_coords.push(clipped_surface_rect.max.y); for y in 0 .. y_coords.len()-1 { let y0 = y_coords[y]; @@ -877,18 +892,11 @@ fn prepare_interned_prim_for_render( let create_task = true; - let r = DeviceRect::new(DevicePoint::new(x0, y0), DevicePoint::new(x1, y1)); - - let x0 = r.min.x; - let y0 = r.min.y; - let x1 = r.max.x; - let y1 = r.max.y; - let segment = add_segment( - x0, - y0, - x1, - y1, + x0 as f32, + y0 as f32, + x1 as f32, + y1 as f32, create_task, prim_instance, prim_spatial_node_index, @@ -917,10 +925,12 @@ fn prepare_interned_prim_for_render( } QuadRenderStrategy::NinePatch { clip_rect, radius } => { let surface = &frame_state.surfaces[pic_context.surface_index.0]; - let clipped_surface_rect = surface.get_surface_rect( + let Some(clipped_surface_rect) = surface.get_surface_rect( &prim_instance.vis.clip_chain.pic_coverage_rect, frame_context.spatial_tree, - ).expect("bug: what can cause this?"); + ) else { + return; + }; let unclipped_surface_rect = surface.map_to_device_rect( &prim_instance.vis.clip_chain.pic_coverage_rect, @@ -943,17 +953,17 @@ fn prepare_interned_prim_for_render( let surface_rect_0 = surface.map_to_device_rect( &pic_corner_0, frame_context.spatial_tree, - ); + ).round_out().to_i32(); let surface_rect_1 = surface.map_to_device_rect( &pic_corner_1, frame_context.spatial_tree, - ); + ).round_out().to_i32(); - let p0 = surface_rect_0.min.floor(); - let p1 = surface_rect_0.max.ceil(); - let p2 = surface_rect_1.min.floor(); - let p3 = surface_rect_1.max.ceil(); + let p0 = surface_rect_0.min; + let p1 = surface_rect_0.max; + let p2 = surface_rect_1.min; + let p3 = surface_rect_1.max; let mut x_coords = [p0.x, p1.x, p2.x, p3.x]; let mut y_coords = [p0.y, p1.y, p2.y, p3.y]; @@ -985,7 +995,10 @@ fn prepare_interned_prim_for_render( true }; - let r = DeviceRect::new(DevicePoint::new(x0, y0), DevicePoint::new(x1, y1)); + let r = DeviceIntRect::new( + DeviceIntPoint::new(x0, y0), + DeviceIntPoint::new(x1, y1), + ); let r = match r.intersection(&clipped_surface_rect) { Some(r) => r, @@ -994,16 +1007,11 @@ fn prepare_interned_prim_for_render( } }; - let x0 = r.min.x; - let y0 = r.min.y; - let x1 = r.max.x; - let y1 = r.max.y; - let segment = add_segment( - x0, - y0, - x1, - y1, + r.min.x as f32, + r.min.y as f32, + r.max.x as f32, + r.max.y as f32, create_task, prim_instance, prim_spatial_node_index, @@ -1138,7 +1146,7 @@ fn prepare_interned_prim_for_render( let stops_address = GradientGpuBlockBuilder::build( prim_data.reverse_stops, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, &prim_data.stops, ); @@ -1296,8 +1304,8 @@ fn prepare_interned_prim_for_render( .clipped_local_rect .cast_unit(); - let main_prim_address = write_prim_blocks( - frame_state.frame_gpu_data, + let prim_address_f = write_prim_blocks( + &mut frame_state.frame_gpu_data.f32, prim_local_rect, prim_instance.vis.clip_chain.local_clip_rect, PremultipliedColorF::WHITE, @@ -1333,7 +1341,7 @@ fn prepare_interned_prim_for_render( let masks = MaskSubPass { clip_node_range, prim_spatial_node_index, - main_prim_address, + prim_address_f, }; // Add the mask as a sub-pass of the picture @@ -1353,30 +1361,22 @@ fn prepare_interned_prim_for_render( let device_pixel_scale = surface.device_pixel_scale; let raster_spatial_node_index = surface.raster_spatial_node_index; - let clipped_surface_rect = surface.get_surface_rect( + let Some(clipped_surface_rect) = surface.get_surface_rect( &coverage_rect, frame_context.spatial_tree, - ).expect("bug: what can cause this?"); - - let p0 = clipped_surface_rect.min.floor(); - let x0 = p0.x; - let y0 = p0.y; - - let content_origin = DevicePoint::new(x0, y0); + ) else { + return; + }; // Draw a normal screens-space mask to an alpha target that // can be sampled when compositing this picture. let empty_task = EmptyTask { - content_origin, + content_origin: clipped_surface_rect.min.to_f32(), device_pixel_scale, raster_spatial_node_index, }; - let p1 = clipped_surface_rect.max.ceil(); - let x1 = p1.x; - let y1 = p1.y; - - let task_size = DeviceSize::new(x1 - x0, y1 - y0).round().to_i32(); + let task_size = clipped_surface_rect.size(); let clip_task_id = frame_state.rg_builder.add().init(RenderTask::new_dynamic( task_size, @@ -1406,7 +1406,7 @@ fn prepare_interned_prim_for_render( let masks = MaskSubPass { clip_node_range, prim_spatial_node_index, - main_prim_address, + prim_address_f, }; let clip_task = frame_state.rg_builder.get_task_mut(clip_task_id); @@ -1814,13 +1814,19 @@ pub fn update_clip_task( unadjusted_device_rect, device_pixel_scale, ); + + if device_rect.size().to_i32().is_empty() { + log::warn!("Bad adjusted clip task size {:?} (was {:?})", device_rect.size(), unadjusted_device_rect.size()); + return false; + } + let clip_task_id = RenderTaskKind::new_mask( device_rect, instance.vis.clip_chain.clips_range, root_spatial_node_index, frame_state.clip_store, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.resource_cache, frame_state.rg_builder, &mut data_stores.clip, @@ -1865,7 +1871,7 @@ pub fn update_brush_segment_clip_task( return ClipMaskKind::None; } - let device_rect = match frame_state.surfaces[surface_index.0].get_surface_rect( + let unadjusted_device_rect = match frame_state.surfaces[surface_index.0].get_surface_rect( &clip_chain.pic_coverage_rect, frame_context.spatial_tree, ) { @@ -1873,7 +1879,12 @@ pub fn update_brush_segment_clip_task( None => return ClipMaskKind::Clipped, }; - let (device_rect, device_pixel_scale) = adjust_mask_scale_for_max_size(device_rect, device_pixel_scale); + let (device_rect, device_pixel_scale) = adjust_mask_scale_for_max_size(unadjusted_device_rect, device_pixel_scale); + + if device_rect.size().to_i32().is_empty() { + log::warn!("Bad adjusted mask size {:?} (was {:?})", device_rect.size(), unadjusted_device_rect.size()); + return ClipMaskKind::Clipped; + } let clip_task_id = RenderTaskKind::new_mask( device_rect, @@ -1881,7 +1892,7 @@ pub fn update_brush_segment_clip_task( root_spatial_node_index, frame_state.clip_store, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.resource_cache, frame_state.rg_builder, clip_data_store, @@ -2101,15 +2112,17 @@ fn build_segments_if_needed( } // Ensures that the size of mask render tasks are within MAX_MASK_SIZE. -fn adjust_mask_scale_for_max_size(device_rect: DeviceRect, device_pixel_scale: DevicePixelScale) -> (DeviceRect, DevicePixelScale) { +fn adjust_mask_scale_for_max_size(device_rect: DeviceIntRect, device_pixel_scale: DevicePixelScale) -> (DeviceIntRect, DevicePixelScale) { if device_rect.width() > MAX_MASK_SIZE || device_rect.height() > MAX_MASK_SIZE { // round_out will grow by 1 integer pixel if origin is on a // fractional position, so keep that margin for error with -1: - let scale = (MAX_MASK_SIZE - 1.0) / - f32::max(device_rect.width(), device_rect.height()); + let device_rect_f = device_rect.to_f32(); + let scale = (MAX_MASK_SIZE - 1) as f32 / + f32::max(device_rect_f.width(), device_rect_f.height()); let new_device_pixel_scale = device_pixel_scale * Scale::new(scale); - let new_device_rect = (device_rect.to_f32() * Scale::new(scale)) - .round_out(); + let new_device_rect = (device_rect_f * Scale::new(scale)) + .round_out() + .to_i32(); (new_device_rect, new_device_pixel_scale) } else { (device_rect, device_pixel_scale) @@ -2117,7 +2130,7 @@ fn adjust_mask_scale_for_max_size(device_rect: DeviceRect, device_pixel_scale: D } pub fn write_prim_blocks( - builder: &mut GpuBufferBuilder, + builder: &mut GpuBufferBuilderF, prim_rect: LayoutRect, clip_rect: LayoutRect, color: PremultipliedColorF, @@ -2153,7 +2166,7 @@ fn add_segment( prim_instance: &PrimitiveInstance, prim_spatial_node_index: SpatialNodeIndex, raster_spatial_node_index: SpatialNodeIndex, - main_prim_address: GpuBufferAddress, + prim_address_f: GpuBufferAddress, transform_id: TransformPaletteId, aa_flags: EdgeAaSegmentMask, quad_flags: QuadFlags, @@ -2177,7 +2190,7 @@ fn add_segment( raster_spatial_node_index, device_pixel_scale, content_origin, - main_prim_address, + prim_address_f, transform_id, aa_flags, quad_flags, @@ -2189,7 +2202,7 @@ fn add_segment( let masks = MaskSubPass { clip_node_range: prim_instance.vis.clip_chain.clips_range, prim_spatial_node_index, - main_prim_address, + prim_address_f, }; let task = frame_state.rg_builder.get_task_mut(task_id); @@ -2223,7 +2236,7 @@ fn add_composite_prim( segments: &[QuadSegment], ) { let composite_prim_address = write_prim_blocks( - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, rect, rect, color, diff --git a/gfx/wr/webrender/src/prim_store/gradient/conic.rs b/gfx/wr/webrender/src/prim_store/gradient/conic.rs index d9c3f5d350..2c4818095e 100644 --- a/gfx/wr/webrender/src/prim_store/gradient/conic.rs +++ b/gfx/wr/webrender/src/prim_store/gradient/conic.rs @@ -254,7 +254,7 @@ impl ConicGradientTemplate { kind: RenderTaskCacheKeyKind::ConicGradient(cache_key), }, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, false, diff --git a/gfx/wr/webrender/src/prim_store/gradient/linear.rs b/gfx/wr/webrender/src/prim_store/gradient/linear.rs index 85da4b670a..7075daac0d 100644 --- a/gfx/wr/webrender/src/prim_store/gradient/linear.rs +++ b/gfx/wr/webrender/src/prim_store/gradient/linear.rs @@ -522,7 +522,7 @@ impl LinearGradientTemplate { kind: RenderTaskCacheKeyKind::FastLinearGradient(gradient), }, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, false, @@ -552,7 +552,7 @@ impl LinearGradientTemplate { kind: RenderTaskCacheKeyKind::LinearGradient(cache_key), }, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, false, diff --git a/gfx/wr/webrender/src/prim_store/gradient/mod.rs b/gfx/wr/webrender/src/prim_store/gradient/mod.rs index d0b922c579..a0410549b0 100644 --- a/gfx/wr/webrender/src/prim_store/gradient/mod.rs +++ b/gfx/wr/webrender/src/prim_store/gradient/mod.rs @@ -4,7 +4,7 @@ use api::{ColorF, ColorU, GradientStop, PremultipliedColorF}; use api::units::{LayoutRect, LayoutSize, LayoutVector2D}; -use crate::renderer::{GpuBufferAddress, GpuBufferBuilder}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF}; use std::hash; mod linear; @@ -167,7 +167,7 @@ impl GradientGpuBlockBuilder { // Build the gradient data from the supplied stops, reversing them if necessary. pub fn build( reverse_stops: bool, - gpu_buffer_builder: &mut GpuBufferBuilder, + gpu_buffer_builder: &mut GpuBufferBuilderF, src_stops: &[GradientStop], ) -> GpuBufferAddress { // Preconditions (should be ensured by DisplayListBuilder): diff --git a/gfx/wr/webrender/src/prim_store/gradient/radial.rs b/gfx/wr/webrender/src/prim_store/gradient/radial.rs index f3f20f9a55..4d91b28633 100644 --- a/gfx/wr/webrender/src/prim_store/gradient/radial.rs +++ b/gfx/wr/webrender/src/prim_store/gradient/radial.rs @@ -220,7 +220,7 @@ impl RadialGradientTemplate { kind: RenderTaskCacheKeyKind::RadialGradient(cache_key), }, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, false, diff --git a/gfx/wr/webrender/src/prim_store/image.rs b/gfx/wr/webrender/src/prim_store/image.rs index 6007b4ba9a..8a05965536 100644 --- a/gfx/wr/webrender/src/prim_store/image.rs +++ b/gfx/wr/webrender/src/prim_store/image.rs @@ -257,7 +257,7 @@ impl ImageData { kind: RenderTaskCacheKeyKind::Image(image_cache_key), }, frame_state.gpu_cache, - frame_state.frame_gpu_data, + &mut frame_state.frame_gpu_data.f32, frame_state.rg_builder, None, descriptor.is_opaque(), diff --git a/gfx/wr/webrender/src/prim_store/mod.rs b/gfx/wr/webrender/src/prim_store/mod.rs index db5480f597..cc09eab6b1 100644 --- a/gfx/wr/webrender/src/prim_store/mod.rs +++ b/gfx/wr/webrender/src/prim_store/mod.rs @@ -1312,6 +1312,37 @@ impl PrimitiveScratchBuffer { } } + pub fn push_debug_rect_with_stroke_width( + &mut self, + rect: WorldRect, + border: ColorF, + stroke_width: f32 + ) { + let top_edge = WorldRect::new( + WorldPoint::new(rect.min.x + stroke_width, rect.min.y), + WorldPoint::new(rect.max.x - stroke_width, rect.min.y + stroke_width) + ); + self.push_debug_rect(top_edge * DevicePixelScale::new(1.0), border, border); + + let bottom_edge = WorldRect::new( + WorldPoint::new(rect.min.x + stroke_width, rect.max.y - stroke_width), + WorldPoint::new(rect.max.x - stroke_width, rect.max.y) + ); + self.push_debug_rect(bottom_edge * DevicePixelScale::new(1.0), border, border); + + let right_edge = WorldRect::new( + WorldPoint::new(rect.max.x - stroke_width, rect.min.y), + rect.max + ); + self.push_debug_rect(right_edge * DevicePixelScale::new(1.0), border, border); + + let left_edge = WorldRect::new( + rect.min, + WorldPoint::new(rect.min.x + stroke_width, rect.max.y) + ); + self.push_debug_rect(left_edge * DevicePixelScale::new(1.0), border, border); + } + #[allow(dead_code)] pub fn push_debug_rect( &mut self, diff --git a/gfx/wr/webrender/src/render_target.rs b/gfx/wr/webrender/src/render_target.rs index 0db77d5ce0..f2d1c24c10 100644 --- a/gfx/wr/webrender/src/render_target.rs +++ b/gfx/wr/webrender/src/render_target.rs @@ -24,7 +24,7 @@ use crate::prim_store::gradient::{ FastLinearGradientInstance, LinearGradientInstance, RadialGradientInstance, ConicGradientInstance, }; -use crate::renderer::{GpuBufferBuilder, GpuBufferAddress}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilder}; use crate::render_backend::DataStores; use crate::render_task::{RenderTaskKind, RenderTaskAddress, SubPass}; use crate::render_task::{RenderTask, ScalingTask, SvgFilterInfo, MaskSubPass}; @@ -104,6 +104,7 @@ pub trait RenderTarget { _z_generator: &mut ZBufferIdGenerator, _prim_instances: &[PrimitiveInstance], _cmd_buffers: &CommandBufferList, + _gpu_buffer_builder: &mut GpuBufferBuilder, ) { } @@ -183,6 +184,7 @@ impl RenderTargetList { z_generator: &mut ZBufferIdGenerator, prim_instances: &[PrimitiveInstance], cmd_buffers: &CommandBufferList, + gpu_buffer_builder: &mut GpuBufferBuilder, ) { if self.targets.is_empty() { return; @@ -198,6 +200,7 @@ impl RenderTargetList { z_generator, prim_instances, cmd_buffers, + gpu_buffer_builder, ); } } @@ -274,10 +277,10 @@ impl RenderTarget for ColorRenderTarget { z_generator: &mut ZBufferIdGenerator, prim_instances: &[PrimitiveInstance], cmd_buffers: &CommandBufferList, + gpu_buffer_builder: &mut GpuBufferBuilder, ) { profile_scope!("build"); let mut merged_batches = AlphaBatchContainer::new(None); - let mut gpu_buffer_builder = GpuBufferBuilder::new(); for task_id in &self.alpha_tasks { profile_scope!("alpha_task"); @@ -326,7 +329,7 @@ impl RenderTarget for ColorRenderTarget { pic_task.surface_spatial_node_index, z_generator, prim_instances, - &mut gpu_buffer_builder, + gpu_buffer_builder, segments, ); }); @@ -376,13 +379,14 @@ impl RenderTarget for ColorRenderTarget { add_quad_to_batch( render_task_address, info.transform_id, - info.prim_address, + info.prim_address_f, info.quad_flags, info.edge_flags, INVALID_SEGMENT_INDEX as u8, RenderTaskId::INVALID, ZBufferId(0), render_tasks, + gpu_buffer_builder, |_, instance| { if info.prim_needs_scissor_rect { self.prim_instances_with_scissor @@ -921,6 +925,7 @@ fn add_svg_filter_instances( kind, input_count, generic_int, + padding: 0, extra_data_address: extra_data_address.unwrap_or(GpuCacheAddress::INVALID), }; @@ -978,7 +983,7 @@ fn build_mask_tasks( let (clip_address, fast_path) = match clip_node.item.kind { ClipItemKind::RoundedRectangle { rect, radius, mode } => { let (fast_path, clip_address) = if radius.is_uniform().is_some() { - let mut writer = gpu_buffer_builder.write_blocks(3); + let mut writer = gpu_buffer_builder.f32.write_blocks(3); writer.push_one(rect); writer.push_one([radius.top_left.width, 0.0, 0.0, 0.0]); writer.push_one([mode as i32 as f32, 0.0, 0.0, 0.0]); @@ -986,7 +991,7 @@ fn build_mask_tasks( (true, clip_address) } else { - let mut writer = gpu_buffer_builder.write_blocks(4); + let mut writer = gpu_buffer_builder.f32.write_blocks(4); writer.push_one(rect); writer.push_one([ radius.top_left.width, @@ -1011,7 +1016,7 @@ fn build_mask_tasks( ClipItemKind::Rectangle { rect, mode, .. } => { assert_eq!(mode, ClipMode::Clip); - let mut writer = gpu_buffer_builder.write_blocks(3); + let mut writer = gpu_buffer_builder.f32.write_blocks(3); writer.push_one(rect); writer.push_one([0.0, 0.0, 0.0, 0.0]); writer.push_one([mode as i32 as f32, 0.0, 0.0, 0.0]); @@ -1043,7 +1048,7 @@ fn build_mask_tasks( for tile in clip_store.visible_mask_tiles(&clip_instance) { let clip_prim_address = write_prim_blocks( - gpu_buffer_builder, + &mut gpu_buffer_builder.f32, rect, rect, PremultipliedColorF::WHITE, @@ -1067,6 +1072,7 @@ fn build_mask_tasks( tile.task_id, ZBufferId(0), render_tasks, + gpu_buffer_builder, |_, prim| { if clip_needs_scissor_rect { results @@ -1107,7 +1113,7 @@ fn build_mask_tasks( ); let main_prim_address = write_prim_blocks( - gpu_buffer_builder, + &mut gpu_buffer_builder.f32, task_world_rect.cast_unit(), task_world_rect.cast_unit(), PremultipliedColorF::WHITE, @@ -1162,6 +1168,7 @@ fn build_mask_tasks( RenderTaskId::INVALID, ZBufferId(0), render_tasks, + gpu_buffer_builder, |_, prim| { let instance = MaskInstance { prim, @@ -1235,7 +1242,7 @@ fn build_sub_pass( render_task_address, content_rect / device_pixel_scale, target_rect, - masks.main_prim_address, + masks.prim_address_f, masks.prim_spatial_node_index, raster_spatial_node_index, ctx.clip_store, diff --git a/gfx/wr/webrender/src/render_task.rs b/gfx/wr/webrender/src/render_task.rs index 4e920cb356..8889ae1ea6 100644 --- a/gfx/wr/webrender/src/render_task.rs +++ b/gfx/wr/webrender/src/render_task.rs @@ -10,7 +10,7 @@ use crate::clip::{ClipDataStore, ClipItemKind, ClipStore, ClipNodeRange}; use crate::command_buffer::{CommandBufferIndex, QuadFlags}; use crate::spatial_tree::SpatialNodeIndex; use crate::filterdata::SFilterData; -use crate::frame_builder::{FrameBuilderConfig}; +use crate::frame_builder::FrameBuilderConfig; use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle}; use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind, TransformPaletteId}; use crate::internal_types::{CacheTextureId, FastHashMap, TextureSource, Swizzle}; @@ -22,7 +22,7 @@ use crate::prim_store::gradient::{ }; use crate::resource_cache::{ResourceCache, ImageRequest}; use std::{usize, f32, i32, u32}; -use crate::renderer::{GpuBufferAddress, GpuBufferBuilder}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF}; use crate::render_target::{ResolveOp, RenderTargetKind}; use crate::render_task_graph::{PassId, RenderTaskId, RenderTaskGraphBuilder}; use crate::render_task_cache::{RenderTaskCacheEntryHandle, RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskParent}; @@ -46,11 +46,11 @@ fn render_task_sanity_check(size: &DeviceIntSize) { #[repr(C)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct RenderTaskAddress(pub u16); +pub struct RenderTaskAddress(pub i32); impl Into for RenderTaskId { fn into(self) -> RenderTaskAddress { - RenderTaskAddress(self.index as u16) + RenderTaskAddress(self.index as i32) } } @@ -186,7 +186,7 @@ pub struct EmptyTask { pub struct PrimTask { pub device_pixel_scale: DevicePixelScale, pub content_origin: DevicePoint, - pub prim_address: GpuBufferAddress, + pub prim_address_f: GpuBufferAddress, pub prim_spatial_node_index: SpatialNodeIndex, pub raster_spatial_node_index: SpatialNodeIndex, pub transform_id: TransformPaletteId, @@ -520,7 +520,7 @@ impl RenderTaskKind { raster_spatial_node_index: SpatialNodeIndex, device_pixel_scale: DevicePixelScale, content_origin: DevicePoint, - prim_address: GpuBufferAddress, + prim_address_f: GpuBufferAddress, transform_id: TransformPaletteId, edge_flags: EdgeAaSegmentMask, quad_flags: QuadFlags, @@ -532,7 +532,7 @@ impl RenderTaskKind { raster_spatial_node_index, device_pixel_scale, content_origin, - prim_address, + prim_address_f, transform_id, edge_flags, quad_flags, @@ -588,12 +588,12 @@ impl RenderTaskKind { } pub fn new_mask( - outer_rect: DeviceRect, + outer_rect: DeviceIntRect, clip_node_range: ClipNodeRange, root_spatial_node_index: SpatialNodeIndex, clip_store: &mut ClipStore, gpu_cache: &mut GpuCache, - gpu_buffer_builder: &mut GpuBufferBuilder, + gpu_buffer_builder: &mut GpuBufferBuilderF, resource_cache: &mut ResourceCache, rg_builder: &mut RenderTaskGraphBuilder, clip_data_store: &mut ClipDataStore, @@ -610,7 +610,7 @@ impl RenderTaskKind { // TODO(gw): If this ever shows up in a profile, we could pre-calculate // whether a ClipSources contains any box-shadows and skip // this iteration for the majority of cases. - let task_size = outer_rect.size().to_i32(); + let task_size = outer_rect.size(); // If we have a potentially tiled clip mask, clear the mask area first. Otherwise, // the first (primary) clip mask will overwrite all the clip mask pixels with @@ -620,7 +620,7 @@ impl RenderTaskKind { RenderTask::new_dynamic( task_size, RenderTaskKind::CacheMask(CacheMaskTask { - actual_rect: outer_rect, + actual_rect: outer_rect.to_f32(), clip_node_range, root_spatial_node_index, device_pixel_scale, @@ -883,7 +883,7 @@ pub type TaskDependencies = SmallVec<[RenderTaskId;2]>; pub struct MaskSubPass { pub clip_node_range: ClipNodeRange, pub prim_spatial_node_index: SpatialNodeIndex, - pub main_prim_address: GpuBufferAddress, + pub prim_address_f: GpuBufferAddress, } #[cfg_attr(feature = "capture", derive(Serialize))] @@ -940,6 +940,9 @@ impl RenderTask { size: DeviceIntSize, kind: RenderTaskKind, ) -> Self { + if size.is_empty() { + log::warn!("Bad {} render task size: {:?}", kind.as_str(), size); + } RenderTask::new( RenderTaskLocation::Unallocated { size }, kind, diff --git a/gfx/wr/webrender/src/render_task_cache.rs b/gfx/wr/webrender/src/render_task_cache.rs index 0454c1214f..2c81a9824f 100644 --- a/gfx/wr/webrender/src/render_task_cache.rs +++ b/gfx/wr/webrender/src/render_task_cache.rs @@ -22,7 +22,7 @@ use crate::resource_cache::CacheItem; use std::{mem, usize, f32, i32}; use crate::surface::SurfaceBuilder; use crate::texture_cache::{TextureCache, TextureCacheHandle, Eviction, TargetShader}; -use crate::renderer::GpuBufferBuilder; +use crate::renderer::GpuBufferBuilderF; use crate::render_target::RenderTargetKind; use crate::render_task::{RenderTask, StaticRenderTaskSurface, RenderTaskLocation, RenderTaskKind, CachedTask}; use crate::render_task_graph::{RenderTaskGraphBuilder, RenderTaskId}; @@ -228,7 +228,7 @@ impl RenderTaskCache { key: RenderTaskCacheKey, texture_cache: &mut TextureCache, gpu_cache: &mut GpuCache, - gpu_buffer_builder: &mut GpuBufferBuilder, + gpu_buffer_builder: &mut GpuBufferBuilderF, rg_builder: &mut RenderTaskGraphBuilder, user_data: Option<[f32; 4]>, is_opaque: bool, @@ -237,7 +237,7 @@ impl RenderTaskCache { f: F, ) -> Result where - F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilder) -> Result, + F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> Result, { let frame_id = self.frame_id; let size = key.size; diff --git a/gfx/wr/webrender/src/render_task_graph.rs b/gfx/wr/webrender/src/render_task_graph.rs index 29ecf66a2e..6c02de8b65 100644 --- a/gfx/wr/webrender/src/render_task_graph.rs +++ b/gfx/wr/webrender/src/render_task_graph.rs @@ -445,6 +445,13 @@ impl RenderTaskGraphBuilder { ) }; + if surface_size.is_empty() { + // We would panic in the guillotine allocator. Instead, panic here + // with some context. + let task_name = graph.tasks[task_id.index as usize].kind.as_str(); + panic!("{} render task has invalid size {:?}", task_name, surface_size); + } + let format = match kind { RenderTargetKind::Color => ImageFormat::RGBA8, RenderTargetKind::Alpha => ImageFormat::R8, diff --git a/gfx/wr/webrender/src/renderer/gpu_buffer.rs b/gfx/wr/webrender/src/renderer/gpu_buffer.rs index 58a8aa6cbd..c8a2b87b0c 100644 --- a/gfx/wr/webrender/src/renderer/gpu_buffer.rs +++ b/gfx/wr/webrender/src/renderer/gpu_buffer.rs @@ -13,21 +13,57 @@ use crate::renderer::MAX_VERTEX_TEXTURE_WIDTH; use api::units::{DeviceIntRect, DeviceIntSize, LayoutRect, PictureRect, DeviceRect}; -use api::{PremultipliedColorF}; +use api::{PremultipliedColorF, ImageFormat}; use crate::device::Texel; use crate::render_task_graph::{RenderTaskGraph, RenderTaskId}; +pub struct GpuBufferBuilder { + pub i32: GpuBufferBuilderI, + pub f32: GpuBufferBuilderF, +} + +pub type GpuBufferF = GpuBuffer; +pub type GpuBufferBuilderF = GpuBufferBuilderImpl; + +pub type GpuBufferI = GpuBuffer; +pub type GpuBufferBuilderI = GpuBufferBuilderImpl; + +unsafe impl Texel for GpuBufferBlockF { + fn image_format() -> ImageFormat { ImageFormat::RGBAF32 } +} + +unsafe impl Texel for GpuBufferBlockI { + fn image_format() -> ImageFormat { ImageFormat::RGBAI32 } +} -unsafe impl Texel for GpuBufferBlock {} +impl Default for GpuBufferBlockF { + fn default() -> Self { + GpuBufferBlockF::EMPTY + } +} + +impl Default for GpuBufferBlockI { + fn default() -> Self { + GpuBufferBlockI::EMPTY + } +} /// A single texel in RGBAF32 texture - 16 bytes. #[derive(Copy, Clone, Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct GpuBufferBlock { +pub struct GpuBufferBlockF { data: [f32; 4], } +/// A single texel in RGBAI32 texture - 16 bytes. +#[derive(Copy, Clone, Debug, MallocSizeOf)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct GpuBufferBlockI { + data: [i32; 4], +} + #[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] @@ -48,13 +84,17 @@ impl GpuBufferAddress { pub const INVALID: GpuBufferAddress = GpuBufferAddress { u: !0, v: !0 }; } -impl GpuBufferBlock { - pub const EMPTY: Self = GpuBufferBlock { data: [0.0; 4] }; +impl GpuBufferBlockF { + pub const EMPTY: Self = GpuBufferBlockF { data: [0.0; 4] }; +} + +impl GpuBufferBlockI { + pub const EMPTY: Self = GpuBufferBlockI { data: [0; 4] }; } -impl Into for LayoutRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into for LayoutRect { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.min.x, self.min.y, @@ -65,9 +105,9 @@ impl Into for LayoutRect { } } -impl Into for PictureRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into for PictureRect { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.min.x, self.min.y, @@ -78,9 +118,9 @@ impl Into for PictureRect { } } -impl Into for DeviceRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into for DeviceRect { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.min.x, self.min.y, @@ -91,9 +131,9 @@ impl Into for DeviceRect { } } -impl Into for PremultipliedColorF { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into for PremultipliedColorF { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { data: [ self.r, self.g, @@ -104,22 +144,43 @@ impl Into for PremultipliedColorF { } } -impl Into for DeviceIntRect { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl From for GpuBufferBlockF { + fn from(rect: DeviceIntRect) -> Self { + GpuBufferBlockF { + data: [ + rect.min.x as f32, + rect.min.y as f32, + rect.max.x as f32, + rect.max.y as f32, + ], + } + } +} + +impl From for GpuBufferBlockI { + fn from(rect: DeviceIntRect) -> Self { + GpuBufferBlockI { data: [ - self.min.x as f32, - self.min.y as f32, - self.max.x as f32, - self.max.y as f32, + rect.min.x, + rect.min.y, + rect.max.x, + rect.max.y, ], } } } -impl Into for [f32; 4] { - fn into(self) -> GpuBufferBlock { - GpuBufferBlock { +impl Into for [f32; 4] { + fn into(self) -> GpuBufferBlockF { + GpuBufferBlockF { + data: self, + } + } +} + +impl Into for [i32; 4] { + fn into(self) -> GpuBufferBlockI { + GpuBufferBlockI { data: self, } } @@ -132,16 +193,16 @@ struct DeferredBlock { } /// Interface to allow writing multiple GPU blocks, possibly of different types -pub struct GpuBufferWriter<'a> { - buffer: &'a mut Vec, +pub struct GpuBufferWriter<'a, T> { + buffer: &'a mut Vec, deferred: &'a mut Vec, index: usize, block_count: usize, } -impl<'a> GpuBufferWriter<'a> { +impl<'a, T> GpuBufferWriter<'a, T> where T: Texel { fn new( - buffer: &'a mut Vec, + buffer: &'a mut Vec, deferred: &'a mut Vec, index: usize, block_count: usize, @@ -155,7 +216,7 @@ impl<'a> GpuBufferWriter<'a> { } /// Push one (16 byte) block of data in to the writer - pub fn push_one(&mut self, block: B) where B: Into { + pub fn push_one(&mut self, block: B) where B: Into { self.buffer.push(block.into()); } @@ -166,7 +227,7 @@ impl<'a> GpuBufferWriter<'a> { task_id, index: self.buffer.len(), }); - self.buffer.push(GpuBufferBlock::EMPTY); + self.buffer.push(T::default()); } /// Close this writer, returning the GPU address of this set of block(s). @@ -180,20 +241,20 @@ impl<'a> GpuBufferWriter<'a> { } } -impl<'a> Drop for GpuBufferWriter<'a> { +impl<'a, T> Drop for GpuBufferWriter<'a, T> { fn drop(&mut self) { assert_eq!(self.buffer.len(), self.index + self.block_count, "Claimed block_count was not written"); } } -pub struct GpuBufferBuilder { - data: Vec, +pub struct GpuBufferBuilderImpl { + data: Vec, deferred: Vec, } -impl GpuBufferBuilder { +impl GpuBufferBuilderImpl where T: Texel + std::convert::From { pub fn new() -> Self { - GpuBufferBuilder { + GpuBufferBuilderImpl { data: Vec::new(), deferred: Vec::new(), } @@ -202,13 +263,13 @@ impl GpuBufferBuilder { #[allow(dead_code)] pub fn push( &mut self, - blocks: &[GpuBufferBlock], + blocks: &[T], ) -> GpuBufferAddress { assert!(blocks.len() <= MAX_VERTEX_TEXTURE_WIDTH); if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + blocks.len() > MAX_VERTEX_TEXTURE_WIDTH { while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 { - self.data.push(GpuBufferBlock::EMPTY); + self.data.push(T::default()); } } @@ -226,12 +287,12 @@ impl GpuBufferBuilder { pub fn write_blocks( &mut self, block_count: usize, - ) -> GpuBufferWriter { + ) -> GpuBufferWriter { assert!(block_count <= MAX_VERTEX_TEXTURE_WIDTH); if (self.data.len() % MAX_VERTEX_TEXTURE_WIDTH) + block_count > MAX_VERTEX_TEXTURE_WIDTH { while self.data.len() % MAX_VERTEX_TEXTURE_WIDTH != 0 { - self.data.push(GpuBufferBlock::EMPTY); + self.data.push(T::default()); } } @@ -248,11 +309,11 @@ impl GpuBufferBuilder { pub fn finalize( mut self, render_tasks: &RenderTaskGraph, - ) -> GpuBuffer { + ) -> GpuBuffer { let required_len = (self.data.len() + MAX_VERTEX_TEXTURE_WIDTH-1) & !(MAX_VERTEX_TEXTURE_WIDTH-1); for _ in 0 .. required_len - self.data.len() { - self.data.push(GpuBufferBlock::EMPTY); + self.data.push(T::default()); } let len = self.data.len(); @@ -271,18 +332,20 @@ impl GpuBufferBuilder { GpuBuffer { data: self.data, size: DeviceIntSize::new(MAX_VERTEX_TEXTURE_WIDTH as i32, (len / MAX_VERTEX_TEXTURE_WIDTH) as i32), + format: T::image_format(), } } } #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct GpuBuffer { - pub data: Vec, +pub struct GpuBuffer { + pub data: Vec, pub size: DeviceIntSize, + pub format: ImageFormat, } -impl GpuBuffer { +impl GpuBuffer { pub fn is_empty(&self) -> bool { self.data.is_empty() } @@ -292,13 +355,13 @@ impl GpuBuffer { #[test] fn test_gpu_buffer_sizing_push() { let render_task_graph = RenderTaskGraph::new_for_testing(); - let mut builder = GpuBufferBuilder::new(); + let mut builder = GpuBufferBuilderF::new(); - let row = vec![GpuBufferBlock::EMPTY; MAX_VERTEX_TEXTURE_WIDTH]; + let row = vec![GpuBufferBlockF::EMPTY; MAX_VERTEX_TEXTURE_WIDTH]; builder.push(&row); - builder.push(&[GpuBufferBlock::EMPTY]); - builder.push(&[GpuBufferBlock::EMPTY]); + builder.push(&[GpuBufferBlockF::EMPTY]); + builder.push(&[GpuBufferBlockF::EMPTY]); let buffer = builder.finalize(&render_task_graph); assert_eq!(buffer.data.len(), MAX_VERTEX_TEXTURE_WIDTH * 2); @@ -307,20 +370,20 @@ fn test_gpu_buffer_sizing_push() { #[test] fn test_gpu_buffer_sizing_writer() { let render_task_graph = RenderTaskGraph::new_for_testing(); - let mut builder = GpuBufferBuilder::new(); + let mut builder = GpuBufferBuilderF::new(); let mut writer = builder.write_blocks(MAX_VERTEX_TEXTURE_WIDTH); for _ in 0 .. MAX_VERTEX_TEXTURE_WIDTH { - writer.push_one(GpuBufferBlock::EMPTY); + writer.push_one(GpuBufferBlockF::EMPTY); } writer.finish(); let mut writer = builder.write_blocks(1); - writer.push_one(GpuBufferBlock::EMPTY); + writer.push_one(GpuBufferBlockF::EMPTY); writer.finish(); let mut writer = builder.write_blocks(1); - writer.push_one(GpuBufferBlock::EMPTY); + writer.push_one(GpuBufferBlockF::EMPTY); writer.finish(); let buffer = builder.finalize(&render_task_graph); diff --git a/gfx/wr/webrender/src/renderer/mod.rs b/gfx/wr/webrender/src/renderer/mod.rs index 0eded7ffb4..3a058ae8f4 100644 --- a/gfx/wr/webrender/src/renderer/mod.rs +++ b/gfx/wr/webrender/src/renderer/mod.rs @@ -59,7 +59,7 @@ use crate::composite::{CompositorConfig, NativeSurfaceOperationDetails, NativeSu use crate::composite::{TileKind}; use crate::debug_colors; use crate::device::{DepthFunction, Device, DrawTarget, ExternalTexture, GpuFrameId, UploadPBOPool}; -use crate::device::{ReadTarget, ShaderError, Texture, TextureFilter, TextureFlags, TextureSlot}; +use crate::device::{ReadTarget, ShaderError, Texture, TextureFilter, TextureFlags, TextureSlot, Texel}; use crate::device::query::{GpuSampler, GpuTimer}; #[cfg(feature = "capture")] use crate::device::FBOId; @@ -127,7 +127,7 @@ pub(crate) mod init; pub use debug::DebugRenderer; pub use shade::{Shaders, SharedShaders}; pub use vertex::{desc, VertexArrayKind, MAX_VERTEX_TEXTURE_WIDTH}; -pub use gpu_buffer::{GpuBuffer, GpuBufferBuilder, GpuBufferAddress}; +pub use gpu_buffer::{GpuBuffer, GpuBufferF, GpuBufferBuilderF, GpuBufferI, GpuBufferBuilderI, GpuBufferAddress, GpuBufferBuilder}; /// The size of the array of each type of vertex data texture that /// is round-robin-ed each frame during bind_frame_data. Doing this @@ -341,7 +341,8 @@ pub(crate) enum TextureSampler { PrimitiveHeadersF, PrimitiveHeadersI, ClipMask, - GpuBuffer, + GpuBufferF, + GpuBufferI, } impl TextureSampler { @@ -370,7 +371,8 @@ impl Into for TextureSampler { TextureSampler::PrimitiveHeadersF => TextureSlot(7), TextureSampler::PrimitiveHeadersI => TextureSlot(8), TextureSampler::ClipMask => TextureSlot(9), - TextureSampler::GpuBuffer => TextureSlot(10), + TextureSampler::GpuBufferF => TextureSlot(10), + TextureSampler::GpuBufferI => TextureSlot(11), } } } @@ -3616,7 +3618,6 @@ impl Renderer { fn draw_clip_batch_list( &mut self, list: &ClipBatchList, - draw_target: &DrawTarget, projection: &default::Transform3D, stats: &mut RendererStats, ) { @@ -3671,42 +3672,6 @@ impl Renderer { stats, ); } - - // draw image masks - let mut using_scissor = false; - for ((mask_texture_id, clip_rect), items) in list.images.iter() { - let _gm2 = self.gpu_profiler.start_marker("clip images"); - // Some image masks may require scissoring to ensure they don't draw - // outside their task's target bounds. Axis-aligned primitives will - // be clamped inside the shader and should not require scissoring. - // TODO: We currently assume scissor state is off by default for - // alpha targets here, but in the future we may want to track the - // current scissor state so that this can be properly saved and - // restored here. - if let Some(clip_rect) = clip_rect { - if !using_scissor { - self.device.enable_scissor(); - using_scissor = true; - } - let scissor_rect = draw_target.build_scissor_rect(Some(*clip_rect)); - self.device.set_scissor_rect(scissor_rect); - } else if using_scissor { - self.device.disable_scissor(); - using_scissor = false; - } - let textures = BatchTextures::composite_rgb(*mask_texture_id); - self.shaders.borrow_mut().cs_clip_image - .bind(&mut self.device, projection, None, &mut self.renderer_errors, &mut self.profile); - self.draw_instanced_batch( - items, - VertexArrayKind::ClipImage, - &textures, - stats, - ); - } - if using_scissor { - self.device.disable_scissor(); - } } fn draw_alpha_target( @@ -3861,7 +3826,6 @@ impl Renderer { self.set_blend(false, FramebufferKind::Other); self.draw_clip_batch_list( &target.clip_batcher.primary_clips, - &draw_target, projection, stats, ); @@ -3872,7 +3836,6 @@ impl Renderer { self.set_blend_mode_multiply(FramebufferKind::Other); self.draw_clip_batch_list( &target.clip_batcher.secondary_clips, - &draw_target, projection, stats, ); @@ -4452,6 +4415,38 @@ impl Renderer { } } + fn create_gpu_buffer_texture( + &mut self, + buffer: &GpuBuffer, + sampler: TextureSampler, + ) -> Option { + if buffer.is_empty() { + None + } else { + let gpu_buffer_texture = self.device.create_texture( + ImageBufferKind::Texture2D, + buffer.format, + buffer.size.width, + buffer.size.height, + TextureFilter::Nearest, + None, + ); + + self.device.bind_texture( + sampler, + &gpu_buffer_texture, + Swizzle::default(), + ); + + self.device.upload_texture_immediate( + &gpu_buffer_texture, + &buffer.data, + ); + + Some(gpu_buffer_texture) + } + } + fn draw_frame( &mut self, frame: &mut Frame, @@ -4478,31 +4473,14 @@ impl Renderer { // Upload experimental GPU buffer texture if there is any data present // TODO: Recycle these textures, upload via PBO or best approach for platform - let gpu_buffer_texture = if frame.gpu_buffer.is_empty() { - None - } else { - let gpu_buffer_texture = self.device.create_texture( - ImageBufferKind::Texture2D, - ImageFormat::RGBAF32, - frame.gpu_buffer.size.width, - frame.gpu_buffer.size.height, - TextureFilter::Nearest, - None, - ); - - self.device.bind_texture( - TextureSampler::GpuBuffer, - &gpu_buffer_texture, - Swizzle::default(), - ); - - self.device.upload_texture_immediate( - &gpu_buffer_texture, - &frame.gpu_buffer.data, - ); - - Some(gpu_buffer_texture) - }; + let gpu_buffer_texture_f = self.create_gpu_buffer_texture( + &frame.gpu_buffer_f, + TextureSampler::GpuBufferF, + ); + let gpu_buffer_texture_i = self.create_gpu_buffer_texture( + &frame.gpu_buffer_i, + TextureSampler::GpuBufferI, + ); // Determine the present mode and dirty rects, if device_size // is Some(..). If it's None, no composite will occur and only @@ -4761,8 +4739,11 @@ impl Renderer { present_mode, ); - if let Some(gpu_buffer_texture) = gpu_buffer_texture { - self.device.delete_texture(gpu_buffer_texture); + if let Some(gpu_buffer_texture_f) = gpu_buffer_texture_f { + self.device.delete_texture(gpu_buffer_texture_f); + } + if let Some(gpu_buffer_texture_i) = gpu_buffer_texture_i { + self.device.delete_texture(gpu_buffer_texture_i); } frame.has_been_rendered = true; diff --git a/gfx/wr/webrender/src/renderer/shade.rs b/gfx/wr/webrender/src/renderer/shade.rs index 30baee0a19..777bfab44a 100644 --- a/gfx/wr/webrender/src/renderer/shade.rs +++ b/gfx/wr/webrender/src/renderer/shade.rs @@ -254,7 +254,6 @@ impl LazilyCompiledShader { VertexArrayKind::RadialGradient => &desc::RADIAL_GRADIENT, VertexArrayKind::ConicGradient => &desc::CONIC_GRADIENT, VertexArrayKind::Blur => &desc::BLUR, - VertexArrayKind::ClipImage => &desc::CLIP_IMAGE, VertexArrayKind::ClipRect => &desc::CLIP_RECT, VertexArrayKind::ClipBoxShadow => &desc::CLIP_BOX_SHADOW, VertexArrayKind::VectorStencil => &desc::VECTOR_STENCIL, @@ -282,7 +281,8 @@ impl LazilyCompiledShader { ("sGpuCache", TextureSampler::GpuCache), ("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF), ("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI), - ("sGpuBuffer", TextureSampler::GpuBuffer), + ("sGpuBufferF", TextureSampler::GpuBufferF), + ("sGpuBufferI", TextureSampler::GpuBufferI), ], ); } @@ -300,7 +300,8 @@ impl LazilyCompiledShader { ("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF), ("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI), ("sClipMask", TextureSampler::ClipMask), - ("sGpuBuffer", TextureSampler::GpuBuffer), + ("sGpuBufferF", TextureSampler::GpuBufferF), + ("sGpuBufferI", TextureSampler::GpuBufferI), ], ); } @@ -617,7 +618,6 @@ pub struct Shaders { pub cs_clip_rectangle_slow: LazilyCompiledShader, pub cs_clip_rectangle_fast: LazilyCompiledShader, pub cs_clip_box_shadow: LazilyCompiledShader, - pub cs_clip_image: LazilyCompiledShader, // The are "primitive shaders". These shaders draw and blend // final results on screen. They are aware of tile boundaries. @@ -817,16 +817,6 @@ impl Shaders { profile, )?; - let cs_clip_image = LazilyCompiledShader::new( - ShaderKind::ClipCache(VertexArrayKind::ClipImage), - "cs_clip_image", - &["TEXTURE_2D"], - device, - options.precache_flags, - &shader_list, - profile, - )?; - let mut cs_scale = Vec::new(); let scale_shader_num = IMAGE_BUFFER_KINDS.len(); // PrimitiveShader is not clonable. Use push() to initialize the vec. @@ -1128,7 +1118,6 @@ impl Shaders { cs_clip_rectangle_slow, cs_clip_rectangle_fast, cs_clip_box_shadow, - cs_clip_image, ps_text_run, ps_text_run_dual_source, ps_quad_textured, @@ -1274,7 +1263,6 @@ impl Shaders { self.cs_clip_rectangle_slow.deinit(device); self.cs_clip_rectangle_fast.deinit(device); self.cs_clip_box_shadow.deinit(device); - self.cs_clip_image.deinit(device); self.ps_text_run.deinit(device); if let Some(shader) = self.ps_text_run_dual_source { shader.deinit(device); diff --git a/gfx/wr/webrender/src/renderer/upload.rs b/gfx/wr/webrender/src/renderer/upload.rs index 0ba053cd76..c987038651 100644 --- a/gfx/wr/webrender/src/renderer/upload.rs +++ b/gfx/wr/webrender/src/renderer/upload.rs @@ -43,6 +43,7 @@ use crate::profiler; use crate::render_api::MemoryReport; pub const BATCH_UPLOAD_TEXTURE_SIZE: DeviceIntSize = DeviceIntSize::new(512, 512); +const BATCH_UPLOAD_FORMAT_COUNT: usize = 4; /// Upload a number of items to texture cache textures. /// @@ -627,10 +628,10 @@ pub struct UploadTexturePool { /// The textures in the pool associated with a last used frame index. /// /// The outer array corresponds to each of teh three supported texture formats. - textures: [VecDeque<(Texture, u64)>; 3], + textures: [VecDeque<(Texture, u64)>; BATCH_UPLOAD_FORMAT_COUNT], // Frame at which to deallocate some textures if there are too many in the pool, // for each format. - delay_texture_deallocation: [u64; 3], + delay_texture_deallocation: [u64; BATCH_UPLOAD_FORMAT_COUNT], current_frame: u64, /// Temporary buffers that are used when using staging uploads + glTexImage2D. @@ -646,8 +647,8 @@ pub struct UploadTexturePool { impl UploadTexturePool { pub fn new() -> Self { UploadTexturePool { - textures: [VecDeque::new(), VecDeque::new(), VecDeque::new()], - delay_texture_deallocation: [0; 3], + textures: [VecDeque::new(), VecDeque::new(), VecDeque::new(), VecDeque::new()], + delay_texture_deallocation: [0; BATCH_UPLOAD_FORMAT_COUNT], current_frame: 0, temporary_buffers: Vec::new(), min_temporary_buffers: 0, @@ -660,7 +661,8 @@ impl UploadTexturePool { ImageFormat::RGBA8 => 0, ImageFormat::BGRA8 => 1, ImageFormat::R8 => 2, - _ => { panic!("unexpected format"); } + ImageFormat::R16 => 3, + _ => { panic!("unexpected format {:?}", format); } } } diff --git a/gfx/wr/webrender/src/renderer/vertex.rs b/gfx/wr/webrender/src/renderer/vertex.rs index ff555363d8..cd73975ddd 100644 --- a/gfx/wr/webrender/src/renderer/vertex.rs +++ b/gfx/wr/webrender/src/renderer/vertex.rs @@ -49,12 +49,12 @@ pub mod desc { VertexAttribute { name: "aBlurRenderTaskAddress", count: 1, - kind: VertexAttributeKind::U16, + kind: VertexAttributeKind::I32, }, VertexAttribute { name: "aBlurSourceTaskAddress", count: 1, - kind: VertexAttributeKind::U16, + kind: VertexAttributeKind::I32, }, VertexAttribute { name: "aBlurDirection", @@ -488,53 +488,6 @@ pub mod desc { ], }; - pub const CLIP_IMAGE: VertexDescriptor = VertexDescriptor { - vertex_attributes: &[VertexAttribute { - name: "aPosition", - count: 2, - kind: VertexAttributeKind::U8Norm, - }], - instance_attributes: &[ - // common clip attributes - VertexAttribute { - name: "aClipDeviceArea", - count: 4, - kind: VertexAttributeKind::F32, - }, - VertexAttribute { - name: "aClipOrigins", - count: 4, - kind: VertexAttributeKind::F32, - }, - VertexAttribute { - name: "aDevicePixelScale", - count: 1, - kind: VertexAttributeKind::F32, - }, - VertexAttribute { - name: "aTransformIds", - count: 2, - kind: VertexAttributeKind::I32, - }, - // specific clip attributes - VertexAttribute { - name: "aClipTileRect", - count: 4, - kind: VertexAttributeKind::F32, - }, - VertexAttribute { - name: "aClipDataResourceAddress", - count: 2, - kind: VertexAttributeKind::U16, - }, - VertexAttribute { - name: "aClipLocalRect", - count: 4, - kind: VertexAttributeKind::F32, - }, - ], - }; - pub const GPU_CACHE_UPDATE: VertexDescriptor = VertexDescriptor { vertex_attributes: &[ VertexAttribute { @@ -574,17 +527,17 @@ pub mod desc { VertexAttribute { name: "aFilterRenderTaskAddress", count: 1, - kind: VertexAttributeKind::U16, + kind: VertexAttributeKind::I32, }, VertexAttribute { name: "aFilterInput1TaskAddress", count: 1, - kind: VertexAttributeKind::U16, + kind: VertexAttributeKind::I32, }, VertexAttribute { name: "aFilterInput2TaskAddress", count: 1, - kind: VertexAttributeKind::U16, + kind: VertexAttributeKind::I32, }, VertexAttribute { name: "aFilterKind", @@ -601,6 +554,11 @@ pub mod desc { count: 1, kind: VertexAttributeKind::U16, }, + VertexAttribute { + name: "aUnused", + count: 1, + kind: VertexAttributeKind::U16, + }, VertexAttribute { name: "aFilterExtraDataAddress", count: 2, @@ -809,7 +767,6 @@ pub mod desc { pub enum VertexArrayKind { Primitive, Blur, - ClipImage, ClipRect, ClipBoxShadow, VectorStencil, @@ -1038,7 +995,6 @@ pub struct RendererVAOs { blur_vao: VAO, clip_rect_vao: VAO, clip_box_shadow_vao: VAO, - clip_image_vao: VAO, border_vao: VAO, line_vao: VAO, scale_vao: VAO, @@ -1086,7 +1042,6 @@ impl RendererVAOs { clip_rect_vao: device.create_vao_with_new_instances(&desc::CLIP_RECT, &prim_vao), clip_box_shadow_vao: device .create_vao_with_new_instances(&desc::CLIP_BOX_SHADOW, &prim_vao), - clip_image_vao: device.create_vao_with_new_instances(&desc::CLIP_IMAGE, &prim_vao), border_vao: device.create_vao_with_new_instances(&desc::BORDER, &prim_vao), scale_vao: device.create_vao_with_new_instances(&desc::SCALE, &prim_vao), line_vao: device.create_vao_with_new_instances(&desc::LINE, &prim_vao), @@ -1109,7 +1064,6 @@ impl RendererVAOs { device.delete_vao(self.resolve_vao); device.delete_vao(self.clip_rect_vao); device.delete_vao(self.clip_box_shadow_vao); - device.delete_vao(self.clip_image_vao); device.delete_vao(self.fast_linear_gradient_vao); device.delete_vao(self.linear_gradient_vao); device.delete_vao(self.radial_gradient_vao); @@ -1131,7 +1085,6 @@ impl ops::Index for RendererVAOs { fn index(&self, kind: VertexArrayKind) -> &VAO { match kind { VertexArrayKind::Primitive => &self.prim_vao, - VertexArrayKind::ClipImage => &self.clip_image_vao, VertexArrayKind::ClipRect => &self.clip_rect_vao, VertexArrayKind::ClipBoxShadow => &self.clip_box_shadow_vao, VertexArrayKind::Blur => &self.blur_vao, diff --git a/gfx/wr/webrender/src/resource_cache.rs b/gfx/wr/webrender/src/resource_cache.rs index 9459bf86da..349be25cb8 100644 --- a/gfx/wr/webrender/src/resource_cache.rs +++ b/gfx/wr/webrender/src/resource_cache.rs @@ -34,7 +34,7 @@ use crate::profiler::{self, TransactionProfile, bytes_to_mb}; use crate::render_task_graph::{RenderTaskId, RenderTaskGraphBuilder}; use crate::render_task_cache::{RenderTaskCache, RenderTaskCacheKey, RenderTaskParent}; use crate::render_task_cache::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle}; -use crate::renderer::GpuBufferBuilder; +use crate::renderer::GpuBufferBuilderF; use crate::surface::SurfaceBuilder; use euclid::point2; use smallvec::SmallVec; @@ -594,7 +594,7 @@ impl ResourceCache { &mut self, key: RenderTaskCacheKey, gpu_cache: &mut GpuCache, - gpu_buffer_builder: &mut GpuBufferBuilder, + gpu_buffer_builder: &mut GpuBufferBuilderF, rg_builder: &mut RenderTaskGraphBuilder, user_data: Option<[f32; 4]>, is_opaque: bool, @@ -603,7 +603,7 @@ impl ResourceCache { f: F, ) -> RenderTaskId where - F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilder) -> RenderTaskId, + F: FnOnce(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> RenderTaskId, { self.cached_render_tasks.request_render_task( key, @@ -2087,14 +2087,14 @@ impl ResourceCache { index, } } - #[cfg(not(target_os = "macos"))] + #[cfg(not(any(target_os = "macos", target_os = "ios")))] FontTemplate::Native(native) => { PlainFontTemplate { data: native.path.to_string_lossy().to_string(), index: native.index, } } - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "ios"))] FontTemplate::Native(native) => { PlainFontTemplate { data: native.name, diff --git a/gfx/wr/webrender/src/spatial_node.rs b/gfx/wr/webrender/src/spatial_node.rs index 9a2039e37b..6bf1313e0d 100644 --- a/gfx/wr/webrender/src/spatial_node.rs +++ b/gfx/wr/webrender/src/spatial_node.rs @@ -673,7 +673,7 @@ impl SpatialNode { pub fn prepare_state_for_children(&self, state: &mut TransformUpdateState) { state.current_coordinate_system_id = self.coordinate_system_id; - state.is_ancestor_or_self_zooming = self.is_async_zooming; + state.is_ancestor_or_self_zooming = self.is_ancestor_or_self_zooming; state.invertible &= self.invertible; // The transformation we are passing is the transformation of the parent diff --git a/gfx/wr/webrender/src/spatial_tree.rs b/gfx/wr/webrender/src/spatial_tree.rs index c2cd422076..0aa6bb5296 100644 --- a/gfx/wr/webrender/src/spatial_tree.rs +++ b/gfx/wr/webrender/src/spatial_tree.rs @@ -2042,3 +2042,46 @@ fn test_world_transforms() { st.get_world_viewport_transform(scroll).into_transform(), LayoutToWorldTransform::identity()); } + +/// Tests that a spatial node that is async zooming and all of its descendants +/// are correctly marked as having themselves an ancestor that is zooming. +#[test] +fn test_is_ancestor_or_self_zooming() { + let mut cst = SceneSpatialTree::new(); + let root_reference_frame_index = cst.root_reference_frame_index(); + + let root = add_reference_frame( + &mut cst, + root_reference_frame_index, + LayoutTransform::identity(), + LayoutVector2D::zero(), + SpatialTreeItemKey::new(0, 0), + ); + let child1 = add_reference_frame( + &mut cst, + root, + LayoutTransform::identity(), + LayoutVector2D::zero(), + SpatialTreeItemKey::new(0, 1), + ); + let child2 = add_reference_frame( + &mut cst, + child1, + LayoutTransform::identity(), + LayoutVector2D::zero(), + SpatialTreeItemKey::new(0, 2), + ); + + let mut st = SpatialTree::new(); + st.apply_updates(cst.end_frame_and_get_pending_updates()); + + // Mark the root node as async zooming + st.get_spatial_node_mut(root).is_async_zooming = true; + st.update_tree(&SceneProperties::new()); + + // Ensure that the root node and all descendants are marked as having + // themselves or an ancestor zooming + assert!(st.get_spatial_node(root).is_ancestor_or_self_zooming); + assert!(st.get_spatial_node(child1).is_ancestor_or_self_zooming); + assert!(st.get_spatial_node(child2).is_ancestor_or_self_zooming); +} diff --git a/gfx/wr/webrender/src/telemetry.rs b/gfx/wr/webrender/src/telemetry.rs index 9b4c02d68e..5fd67bb80c 100644 --- a/gfx/wr/webrender/src/telemetry.rs +++ b/gfx/wr/webrender/src/telemetry.rs @@ -2,6 +2,7 @@ * 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/. */ +#[cfg(feature = "gecko")] use glean::TimerId; #[cfg(feature = "gecko")] use firefox_on_glean::metrics::wr; @@ -9,16 +10,19 @@ use std::time::Duration; pub struct Telemetry; +#[cfg(not(feature = "gecko"))] +pub struct TimerId; + /// Defines the interface for hooking up an external telemetry reporter to WR. #[cfg(not(feature = "gecko"))] impl Telemetry { pub fn record_rasterize_blobs_time(_duration: Duration) { } - pub fn start_framebuild_time() -> TimerId { TimerId { id: 0 } } + pub fn start_framebuild_time() -> TimerId { TimerId } pub fn stop_and_accumulate_framebuild_time(_id: TimerId) { } pub fn record_renderer_time(_duration: Duration) { } pub fn record_renderer_time_no_sc(_duration: Duration) { } pub fn record_scenebuild_time(_duration: Duration) { } - pub fn start_sceneswap_time() -> TimerId { TimerId { id: 0 } } + pub fn start_sceneswap_time() -> TimerId { TimerId } pub fn stop_and_accumulate_sceneswap_time(_id: TimerId) { } pub fn cancel_sceneswap_time(_id: TimerId) { } pub fn record_texture_cache_update_time(_duration: Duration) { } diff --git a/gfx/wr/webrender_api/src/font.rs b/gfx/wr/webrender_api/src/font.rs index d4f3057a7c..fc245ddfab 100644 --- a/gfx/wr/webrender_api/src/font.rs +++ b/gfx/wr/webrender_api/src/font.rs @@ -5,7 +5,7 @@ use peek_poke::PeekPoke; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; -#[cfg(not(target_os = "macos"))] +#[cfg(not(any(target_os = "macos", target_os = "ios")))] use std::path::PathBuf; use std::sync::Arc; // local imports @@ -52,14 +52,14 @@ impl FontSize { pub fn to_f64_px(&self) -> f64 { self.0 as f64 } } -#[cfg(not(target_os = "macos"))] +#[cfg(not(any(target_os = "macos", target_os = "ios")))] #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct NativeFontHandle { pub path: PathBuf, pub index: u32, } -#[cfg(target_os = "macos")] +#[cfg(any(target_os = "macos", target_os = "ios"))] #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct NativeFontHandle { pub name: String, @@ -236,13 +236,13 @@ impl Default for FontInstanceFlags { FontInstanceFlags::SUBPIXEL_POSITION } - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "ios"))] fn default() -> FontInstanceFlags { FontInstanceFlags::SUBPIXEL_POSITION | FontInstanceFlags::FONT_SMOOTHING } - #[cfg(not(any(target_os = "macos", target_os = "windows")))] + #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))] fn default() -> FontInstanceFlags { FontInstanceFlags::SUBPIXEL_POSITION } @@ -332,14 +332,14 @@ impl Default for FontInstancePlatformOptions { } } -#[cfg(target_os = "macos")] +#[cfg(any(target_os = "macos", target_os = "ios"))] #[repr(C)] #[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub unused: u32, } -#[cfg(target_os = "macos")] +#[cfg(any(target_os = "macos", target_os = "ios"))] impl Default for FontInstancePlatformOptions { fn default() -> FontInstancePlatformOptions { FontInstancePlatformOptions { @@ -348,7 +348,7 @@ impl Default for FontInstancePlatformOptions { } } -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))] #[repr(u8)] #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub enum FontLCDFilter { @@ -358,7 +358,7 @@ pub enum FontLCDFilter { Legacy, } -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))] #[repr(u8)] #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub enum FontHinting { @@ -369,7 +369,7 @@ pub enum FontHinting { LCD, } -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))] #[repr(C)] #[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { @@ -377,7 +377,7 @@ pub struct FontInstancePlatformOptions { pub hinting: FontHinting, } -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))] impl Default for FontInstancePlatformOptions { fn default() -> FontInstancePlatformOptions { FontInstancePlatformOptions { diff --git a/gfx/wr/webrender_build/src/shader_features.rs b/gfx/wr/webrender_build/src/shader_features.rs index 2c5d03dc92..780a24a1aa 100644 --- a/gfx/wr/webrender_build/src/shader_features.rs +++ b/gfx/wr/webrender_build/src/shader_features.rs @@ -66,7 +66,6 @@ pub fn get_shader_features(flags: ShaderFeatureFlags) -> ShaderFeatures { // Clip shaders shaders.insert("cs_clip_rectangle", vec![String::new(), "FAST_PATH".to_string()]); - shaders.insert("cs_clip_image", vec!["TEXTURE_2D".to_string()]); shaders.insert("cs_clip_box_shadow", vec!["TEXTURE_2D".to_string()]); // Cache shaders diff --git a/gfx/wr/wr_glyph_rasterizer/Cargo.toml b/gfx/wr/wr_glyph_rasterizer/Cargo.toml index 1d94a460cc..b06cd0f084 100644 --- a/gfx/wr/wr_glyph_rasterizer/Cargo.toml +++ b/gfx/wr/wr_glyph_rasterizer/Cargo.toml @@ -25,7 +25,7 @@ tracy-rs = "0.1.2" log = "0.4" lazy_static = "1" fxhash = "0.2.1" -glean = { version = "57.0.0", optional = true } +glean = { version = "58.1.0", optional = true } firefox-on-glean = { version = "0.1.0", optional = true } serde = { optional = true, version = "1.0", features = ["serde_derive"] } @@ -37,14 +37,14 @@ glutin = "0.28" rayon = "1" winit = "0.26" -[target.'cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))'.dependencies] +[target.'cfg(any(target_os = "android", all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies] freetype = { version = "0.7", default-features = false } libc = "0.2" [target.'cfg(target_os = "windows")'.dependencies] dwrote = "0.11" -[target.'cfg(target_os = "macos")'.dependencies] +[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] core-foundation = "0.9.2" core-graphics = "0.23" core-text = { version = "20.1", default-features = false } diff --git a/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs b/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs index 15075bacbf..82555c8a06 100644 --- a/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs +++ b/gfx/wr/wr_glyph_rasterizer/src/gamma_lut.rs @@ -168,7 +168,7 @@ impl ColorLut for ColorU { // so we can get linear values. // CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. // The color space used does not appear to affect this choice. -#[cfg(target_os="macos")] +#[cfg(any(target_os="macos", target_os = "ios"))] fn get_inverse_gamma_table_coregraphics_smoothing() -> [u8; 256] { let mut table = [0u8; 256]; @@ -250,7 +250,7 @@ pub fn build_gamma_correcting_lut(table: &mut [u8; 256], src: u8, contrast: f32, pub struct GammaLut { tables: [[u8; 256]; 1 << LUM_BITS], - #[cfg(target_os="macos")] + #[cfg(any(target_os="macos", target_os="ios"))] cg_inverse_gamma: [u8; 256], } @@ -280,12 +280,12 @@ impl GammaLut { } pub fn new(contrast: f32, paint_gamma: f32, device_gamma: f32) -> GammaLut { - #[cfg(target_os="macos")] + #[cfg(any(target_os="macos", target_os="ios"))] let mut table = GammaLut { tables: [[0; 256]; 1 << LUM_BITS], cg_inverse_gamma: get_inverse_gamma_table_coregraphics_smoothing(), }; - #[cfg(not(target_os="macos"))] + #[cfg(not(any(target_os="macos", target_os="ios")))] let mut table = GammaLut { tables: [[0; 256]; 1 << LUM_BITS], }; @@ -337,7 +337,7 @@ impl GammaLut { } } - #[cfg(target_os="macos")] + #[cfg(any(target_os="macos", target_os="ios"))] pub fn coregraphics_convert_to_linear(&self, pixels: &mut [u8]) { for pixel in pixels.chunks_mut(4) { pixel[0] = self.cg_inverse_gamma[pixel[0] as usize]; diff --git a/gfx/wr/wr_glyph_rasterizer/src/lib.rs b/gfx/wr/wr_glyph_rasterizer/src/lib.rs index 27ceb71992..3cf95d7c31 100644 --- a/gfx/wr/wr_glyph_rasterizer/src/lib.rs +++ b/gfx/wr/wr_glyph_rasterizer/src/lib.rs @@ -9,7 +9,7 @@ //! ## Usage //! -#[cfg(any(target_os = "macos", target_os = "windows"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "windows"))] mod gamma_lut; mod rasterizer; mod telemetry; @@ -38,18 +38,18 @@ extern crate serde; extern crate malloc_size_of; pub mod platform { - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "ios"))] pub use crate::platform::macos::font; - #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))] + #[cfg(any(target_os = "android", all(unix, not(any(target_os = "ios", target_os = "macos")))))] pub use crate::platform::unix::font; #[cfg(target_os = "windows")] pub use crate::platform::windows::font; - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "ios", target_os = "macos"))] pub mod macos { pub mod font; } - #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))] + #[cfg(any(target_os = "android", all(unix, not(any(target_os = "macos", target_os = "ios")))))] pub mod unix { pub mod font; } -- cgit v1.2.3