From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- gfx/wr/webrender/src/filterdata.rs | 219 +++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 gfx/wr/webrender/src/filterdata.rs (limited to 'gfx/wr/webrender/src/filterdata.rs') diff --git a/gfx/wr/webrender/src/filterdata.rs b/gfx/wr/webrender/src/filterdata.rs new file mode 100644 index 0000000000..d399b2252e --- /dev/null +++ b/gfx/wr/webrender/src/filterdata.rs @@ -0,0 +1,219 @@ +/* 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/. */ + +use std::{hash}; +use crate::gpu_cache::{GpuCacheHandle}; +use crate::frame_builder::FrameBuildingState; +use crate::gpu_cache::GpuDataRequest; +use crate::intern; +use api::{ComponentTransferFuncType}; + + +pub type FilterDataHandle = intern::Handle; + +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub enum SFilterDataComponent { + Identity, + Table(Vec), + Discrete(Vec), + Linear(f32, f32), + Gamma(f32, f32, f32), +} + +impl Eq for SFilterDataComponent {} + +impl hash::Hash for SFilterDataComponent { + fn hash(&self, state: &mut H) { + match self { + SFilterDataComponent::Identity => { + 0.hash(state); + } + SFilterDataComponent::Table(values) => { + 1.hash(state); + values.len().hash(state); + for val in values { + val.to_bits().hash(state); + } + } + SFilterDataComponent::Discrete(values) => { + 2.hash(state); + values.len().hash(state); + for val in values { + val.to_bits().hash(state); + } + } + SFilterDataComponent::Linear(a, b) => { + 3.hash(state); + a.to_bits().hash(state); + b.to_bits().hash(state); + } + SFilterDataComponent::Gamma(a, b, c) => { + 4.hash(state); + a.to_bits().hash(state); + b.to_bits().hash(state); + c.to_bits().hash(state); + } + } + } +} + +impl SFilterDataComponent { + pub fn to_int(&self) -> u32 { + match self { + SFilterDataComponent::Identity => 0, + SFilterDataComponent::Table(_) => 1, + SFilterDataComponent::Discrete(_) => 2, + SFilterDataComponent::Linear(_, _) => 3, + SFilterDataComponent::Gamma(_, _, _) => 4, + } + } + + pub fn from_functype_values( + func_type: ComponentTransferFuncType, + values: &[f32], + ) -> SFilterDataComponent { + match func_type { + ComponentTransferFuncType::Identity => SFilterDataComponent::Identity, + ComponentTransferFuncType::Table => SFilterDataComponent::Table(values.to_vec()), + ComponentTransferFuncType::Discrete => SFilterDataComponent::Discrete(values.to_vec()), + ComponentTransferFuncType::Linear => SFilterDataComponent::Linear(values[0], values[1]), + ComponentTransferFuncType::Gamma => SFilterDataComponent::Gamma(values[0], values[1], values[2]), + } + } +} + +#[derive(Debug, Clone, MallocSizeOf, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct SFilterData { + pub r_func: SFilterDataComponent, + pub g_func: SFilterDataComponent, + pub b_func: SFilterDataComponent, + pub a_func: SFilterDataComponent, +} + +#[derive(Debug, Clone, MallocSizeOf, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct SFilterDataKey { + pub data: SFilterData, +} + +impl intern::InternDebug for SFilterDataKey {} + +#[derive(Debug)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] +pub struct SFilterDataTemplate { + pub data: SFilterData, + pub gpu_cache_handle: GpuCacheHandle, +} + +impl From for SFilterDataTemplate { + fn from(item: SFilterDataKey) -> Self { + SFilterDataTemplate { + data: item.data, + gpu_cache_handle: GpuCacheHandle::new(), + } + } +} + +impl SFilterData { + pub fn is_identity(&self) -> bool { + self.r_func == SFilterDataComponent::Identity + && self.g_func == SFilterDataComponent::Identity + && self.b_func == SFilterDataComponent::Identity + && self.a_func == SFilterDataComponent::Identity + } + + pub fn update(&self, mut request: GpuDataRequest) { + push_component_transfer_data(&self.r_func, &mut request); + push_component_transfer_data(&self.g_func, &mut request); + push_component_transfer_data(&self.b_func, &mut request); + push_component_transfer_data(&self.a_func, &mut request); + assert!(!self.is_identity()); + } +} + +impl SFilterDataTemplate { + /// Update the GPU cache for a given filter data template. This may be called multiple + /// times per frame, by each primitive reference that refers to this interned + /// template. The initial request call to the GPU cache ensures that work is only + /// done if the cache entry is invalid (due to first use or eviction). + pub fn update( + &mut self, + frame_state: &mut FrameBuildingState, + ) { + if let Some(request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) { + self.data.update(request); + } + } +} + +#[derive(Copy, Clone, Debug, MallocSizeOf)] +#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] +pub enum FilterDataIntern {} + +impl intern::Internable for FilterDataIntern { + type Key = SFilterDataKey; + type StoreData = SFilterDataTemplate; + type InternData = (); + const PROFILE_COUNTER: usize = crate::profiler::INTERNED_FILTER_DATA; +} + +fn push_component_transfer_data( + func_comp: &SFilterDataComponent, + request: &mut GpuDataRequest, +) { + match func_comp { + SFilterDataComponent::Identity => {} + SFilterDataComponent::Table(values) | + SFilterDataComponent::Discrete(values) => { + // Push a 256 entry lookup table. + assert!(values.len() > 0); + for i in 0 .. 64 { + let mut arr = [0.0 ; 4]; + for j in 0 .. 4 { + if (values.len() == 1) || (i == 63 && j == 3) { + arr[j] = values[values.len()-1]; + } else { + let c = ((4*i + j) as f32)/255.0; + match func_comp { + SFilterDataComponent::Table(_) => { + let n = (values.len()-1) as f32; + let k = (n * c).floor() as u32; + let ku = k as usize; + assert!(ku < values.len()-1); + arr[j] = values[ku] + (c*n - (k as f32)) * (values[ku+1] - values[ku]); + } + SFilterDataComponent::Discrete(_) => { + let n = values.len() as f32; + let k = (n * c).floor() as usize; + assert!(k < values.len()); + arr[j] = values[k]; + } + SFilterDataComponent::Identity | + SFilterDataComponent::Linear(_,_) | + SFilterDataComponent::Gamma(_,_,_) => { + unreachable!(); + } + } + + } + } + + request.push(arr); + } + } + SFilterDataComponent::Linear(a, b) => { + request.push([*a, *b, 0.0, 0.0]); + } + SFilterDataComponent::Gamma(a, b, c) => { + request.push([*a, *b, *c, 0.0]); + } + } +} -- cgit v1.2.3