From 59203c63bb777a3bacec32fb8830fba33540e809 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:29 +0200 Subject: Adding upstream version 127.0. Signed-off-by: Daniel Baumann --- gfx/webrender_bindings/src/bindings.rs | 98 ++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 21 deletions(-) (limited to 'gfx/webrender_bindings/src/bindings.rs') diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 3fc93fdf13..579453a165 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -36,11 +36,11 @@ use tracy_rs::register_thread_with_profiler; use webrender::sw_compositor::SwCompositor; use webrender::{ api::units::*, api::*, create_webrender_instance, render_api::*, set_profiler_hooks, AsyncPropertySampler, - AsyncScreenshotHandle, Compositor, CompositorCapabilities, CompositorConfig, CompositorSurfaceTransform, - Device, MappableCompositor, MappedTileInfo, NativeSurfaceId, NativeSurfaceInfo, NativeTileId, - PartialPresentCompositor, PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererStats, - SWGLCompositeSurfaceInfo, SceneBuilderHooks, ShaderPrecacheFlags, Shaders, SharedShaders, TextureCacheConfig, - UploadMethod, WebRenderOptions, WindowVisibility, ONE_TIME_USAGE_HINT, + AsyncScreenshotHandle, Compositor, CompositorCapabilities, CompositorConfig, CompositorSurfaceTransform, Device, + MappableCompositor, MappedTileInfo, NativeSurfaceId, NativeSurfaceInfo, NativeTileId, PartialPresentCompositor, + PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererStats, SWGLCompositeSurfaceInfo, + SceneBuilderHooks, ShaderPrecacheFlags, Shaders, SharedShaders, TextureCacheConfig, UploadMethod, WebRenderOptions, + WindowVisibility, ONE_TIME_USAGE_HINT, }; use wr_malloc_size_of::MallocSizeOfOps; @@ -212,36 +212,68 @@ impl DocumentHandle { #[repr(C)] pub struct WrVecU8 { + /// `data` must always be valid for passing to Vec::from_raw_parts. + /// In particular, it must be non-null even if capacity is zero. data: *mut u8, length: usize, capacity: usize, } impl WrVecU8 { - fn into_vec(self) -> Vec { - unsafe { Vec::from_raw_parts(self.data, self.length, self.capacity) } + fn into_vec(mut self) -> Vec { + // Clear self and then drop self. + self.flush_into_vec() } - // Equivalent to `into_vec` but clears self instead of consuming the value. + // Clears self without consuming self. fn flush_into_vec(&mut self) -> Vec { - self.convert_into_vec::() - } - - // Like flush_into_vec, but also does an unsafe conversion to the desired type. - fn convert_into_vec(&mut self) -> Vec { + // Create a Vec using Vec::from_raw_parts. + // + // Here are the safety requirements, verbatim from the documentation of `from_raw_parts`: + // + // > * `ptr` must have been allocated using the global allocator, such as via + // > the [`alloc::alloc`] function. + // > * `T` needs to have the same alignment as what `ptr` was allocated with. + // > (`T` having a less strict alignment is not sufficient, the alignment really + // > needs to be equal to satisfy the [`dealloc`] requirement that memory must be + // > allocated and deallocated with the same layout.) + // > * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + // > to be the same size as the pointer was allocated with. (Because similar to + // > alignment, [`dealloc`] must be called with the same layout `size`.) + // > * `length` needs to be less than or equal to `capacity`. + // > * The first `length` values must be properly initialized values of type `T`. + // > * `capacity` needs to be the capacity that the pointer was allocated with. + // > * The allocated size in bytes must be no larger than `isize::MAX`. + // > See the safety documentation of [`pointer::offset`]. + // + // These comments don't say what to do for zero-capacity vecs which don't have + // an allocation. In particular, the requirement "`ptr` must have been allocated" + // is not met for such vecs. + // + // However, the safety requirements of `slice::from_raw_parts` are more explicit + // about the empty case: + // + // > * `data` must be non-null and aligned even for zero-length slices. One + // > reason for this is that enum layout optimizations may rely on references + // > (including slices of any length) being aligned and non-null to distinguish + // > them from other data. You can obtain a pointer that is usable as `data` + // > for zero-length slices using [`NonNull::dangling()`]. + // + // For the empty case we follow this requirement rather than the more stringent + // requirement from the `Vec::from_raw_parts` docs. let vec = unsafe { - Vec::from_raw_parts( - self.data as *mut T, - self.length / mem::size_of::(), - self.capacity / mem::size_of::(), - ) + Vec::from_raw_parts(self.data, self.length, self.capacity) }; - self.data = ptr::null_mut(); + self.data = ptr::NonNull::dangling().as_ptr(); self.length = 0; self.capacity = 0; vec } + pub fn as_slice(&self) -> &[u8] { + unsafe { core::slice::from_raw_parts(self.data, self.length) } + } + fn from_vec(mut v: Vec) -> WrVecU8 { let w = WrVecU8 { data: v.as_mut_ptr(), @@ -2317,7 +2349,8 @@ pub extern "C" fn wr_api_stop_capture_sequence(dh: &mut DocumentHandle) { #[cfg(target_os = "windows")] fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle { - let wchars = bytes.convert_into_vec::(); + let wchars: Vec = + bytes.as_slice().chunks_exact(2).map(|c| u16::from_ne_bytes([c[0], c[1]])).collect(); NativeFontHandle { path: PathBuf::from(OsString::from_wide(&wchars)), index, @@ -2373,13 +2406,24 @@ pub extern "C" fn wr_resource_updates_add_font_instance( platform_options: *const FontInstancePlatformOptions, variations: &mut WrVecU8, ) { + // Deserialize a sequence of FontVariation objects from the raw bytes. + // Every FontVariation is 8 bytes: one u32 and one f32. + // The code below would look better with slice::chunk_arrays: + // https://github.com/rust-lang/rust/issues/74985 + let variations: Vec = + variations.as_slice().chunks_exact(8).map(|c| { + assert_eq!(c.len(), 8); + let tag = u32::from_ne_bytes([c[0], c[1], c[2], c[3]]); + let value = f32::from_ne_bytes([c[4], c[5], c[6], c[7]]); + FontVariation { tag, value } + }).collect(); txn.add_font_instance( key, font_key, glyph_size, unsafe { options.as_ref().cloned() }, unsafe { platform_options.as_ref().cloned() }, - variations.convert_into_vec::(), + variations, ); } @@ -2756,8 +2800,19 @@ pub extern "C" fn wr_dp_define_sticky_frame( horizontal_bounds: StickyOffsetBounds, applied_offset: LayoutVector2D, key: SpatialTreeItemKey, + animation: *const WrAnimationProperty ) -> WrSpatialId { assert!(unsafe { is_in_main_thread() }); + let anim = unsafe { animation.as_ref() }; + let transform = anim.map(|anim| { + debug_assert!(anim.id > 0); + match anim.effect_type { + WrAnimationType::Transform => { + PropertyBinding::Binding(PropertyBindingKey::new(anim.id), LayoutTransform::identity()) + }, + _ => unreachable!("sticky elements can only have a transform animated") + } + }); let spatial_id = state.frame_builder.dl_builder.define_sticky_frame( parent_spatial_id.to_webrender(state.pipeline_id), content_rect, @@ -2771,6 +2826,7 @@ pub extern "C" fn wr_dp_define_sticky_frame( horizontal_bounds, applied_offset, key, + transform ); WrSpatialId { id: spatial_id.0 } -- cgit v1.2.3