filterdata.rs (7808B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use std::hash; 6 use crate::intern; 7 use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferWriterF}; 8 use api::ComponentTransferFuncType; 9 10 11 pub type FilterDataHandle = intern::Handle<FilterDataIntern>; 12 13 #[derive(Debug, Clone, MallocSizeOf, PartialEq)] 14 #[cfg_attr(feature = "capture", derive(Serialize))] 15 #[cfg_attr(feature = "replay", derive(Deserialize))] 16 pub enum SFilterDataComponent { 17 Identity, 18 Table(Vec<f32>), 19 Discrete(Vec<f32>), 20 Linear(f32, f32), 21 Gamma(f32, f32, f32), 22 } 23 24 impl Eq for SFilterDataComponent {} 25 26 impl hash::Hash for SFilterDataComponent { 27 fn hash<H: hash::Hasher>(&self, state: &mut H) { 28 match self { 29 SFilterDataComponent::Identity => { 30 0.hash(state); 31 } 32 SFilterDataComponent::Table(values) => { 33 1.hash(state); 34 values.len().hash(state); 35 for val in values { 36 val.to_bits().hash(state); 37 } 38 } 39 SFilterDataComponent::Discrete(values) => { 40 2.hash(state); 41 values.len().hash(state); 42 for val in values { 43 val.to_bits().hash(state); 44 } 45 } 46 SFilterDataComponent::Linear(a, b) => { 47 3.hash(state); 48 a.to_bits().hash(state); 49 b.to_bits().hash(state); 50 } 51 SFilterDataComponent::Gamma(a, b, c) => { 52 4.hash(state); 53 a.to_bits().hash(state); 54 b.to_bits().hash(state); 55 c.to_bits().hash(state); 56 } 57 } 58 } 59 } 60 61 impl SFilterDataComponent { 62 pub fn to_int(&self) -> u32 { 63 match self { 64 SFilterDataComponent::Identity => 0, 65 SFilterDataComponent::Table(_) => 1, 66 SFilterDataComponent::Discrete(_) => 2, 67 SFilterDataComponent::Linear(_, _) => 3, 68 SFilterDataComponent::Gamma(_, _, _) => 4, 69 } 70 } 71 72 pub fn from_functype_values( 73 func_type: ComponentTransferFuncType, 74 values: &[f32], 75 ) -> SFilterDataComponent { 76 match func_type { 77 ComponentTransferFuncType::Identity => SFilterDataComponent::Identity, 78 ComponentTransferFuncType::Table => SFilterDataComponent::Table(values.to_vec()), 79 ComponentTransferFuncType::Discrete => SFilterDataComponent::Discrete(values.to_vec()), 80 ComponentTransferFuncType::Linear => SFilterDataComponent::Linear(values[0], values[1]), 81 ComponentTransferFuncType::Gamma => SFilterDataComponent::Gamma(values[0], values[1], values[2]), 82 } 83 } 84 } 85 86 #[derive(Debug, Clone, MallocSizeOf, PartialEq, Eq, Hash)] 87 #[cfg_attr(feature = "capture", derive(Serialize))] 88 #[cfg_attr(feature = "replay", derive(Deserialize))] 89 pub struct SFilterData { 90 pub r_func: SFilterDataComponent, 91 pub g_func: SFilterDataComponent, 92 pub b_func: SFilterDataComponent, 93 pub a_func: SFilterDataComponent, 94 } 95 96 #[derive(Debug, Clone, MallocSizeOf, PartialEq, Eq, Hash)] 97 #[cfg_attr(feature = "capture", derive(Serialize))] 98 #[cfg_attr(feature = "replay", derive(Deserialize))] 99 pub struct SFilterDataKey { 100 pub data: SFilterData, 101 } 102 103 impl intern::InternDebug for SFilterDataKey {} 104 105 #[derive(Debug)] 106 #[cfg_attr(feature = "capture", derive(Serialize))] 107 #[cfg_attr(feature = "replay", derive(Deserialize))] 108 #[derive(MallocSizeOf)] 109 pub struct SFilterDataTemplate { 110 pub data: SFilterData, 111 pub gpu_buffer_address: GpuBufferAddress, 112 } 113 114 impl From<SFilterDataKey> for SFilterDataTemplate { 115 fn from(item: SFilterDataKey) -> Self { 116 SFilterDataTemplate { 117 data: item.data, 118 gpu_buffer_address: GpuBufferAddress::INVALID, 119 } 120 } 121 } 122 123 impl SFilterData { 124 pub fn is_identity(&self) -> bool { 125 self.r_func == SFilterDataComponent::Identity 126 && self.g_func == SFilterDataComponent::Identity 127 && self.b_func == SFilterDataComponent::Identity 128 && self.a_func == SFilterDataComponent::Identity 129 } 130 131 pub fn write_gpu_blocks(&self, gpu_buffer: &mut GpuBufferBuilderF) -> GpuBufferAddress { 132 assert!(!self.is_identity()); 133 let mut writer = gpu_buffer.write_blocks(1024); 134 push_component_transfer_data(&self.r_func, &mut writer); 135 push_component_transfer_data(&self.g_func, &mut writer); 136 push_component_transfer_data(&self.b_func, &mut writer); 137 push_component_transfer_data(&self.a_func, &mut writer); 138 writer.finish() 139 } 140 } 141 142 impl SFilterDataTemplate { 143 /// Update the GPU cache for a given filter data template. This may be called multiple 144 /// times per frame, by each primitive reference that refers to this interned 145 /// template. The initial request call to the GPU cache ensures that work is only 146 /// done if the cache entry is invalid (due to first use or eviction). 147 pub fn write_gpu_blocks( 148 &mut self, 149 gpu_buffer: &mut GpuBufferBuilderF, 150 ) { 151 self.gpu_buffer_address = self.data.write_gpu_blocks(gpu_buffer); 152 } 153 } 154 155 #[derive(Copy, Clone, Debug, MallocSizeOf)] 156 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] 157 pub enum FilterDataIntern {} 158 159 impl intern::Internable for FilterDataIntern { 160 type Key = SFilterDataKey; 161 type StoreData = SFilterDataTemplate; 162 type InternData = (); 163 const PROFILE_COUNTER: usize = crate::profiler::INTERNED_FILTER_DATA; 164 } 165 166 fn push_component_transfer_data( 167 func_comp: &SFilterDataComponent, 168 writer: &mut GpuBufferWriterF, 169 ) { 170 match func_comp { 171 SFilterDataComponent::Identity => {} 172 SFilterDataComponent::Table(values) | 173 SFilterDataComponent::Discrete(values) => { 174 // Push a 256 entry lookup table. 175 assert!(values.len() > 0); 176 for i in 0 .. 64 { 177 let mut arr = [0.0 ; 4]; 178 for j in 0 .. 4 { 179 if (values.len() == 1) || (i == 63 && j == 3) { 180 arr[j] = values[values.len()-1]; 181 } else { 182 let c = ((4*i + j) as f32)/255.0; 183 match func_comp { 184 SFilterDataComponent::Table(_) => { 185 let n = (values.len()-1) as f32; 186 let k = (n * c).floor() as u32; 187 let ku = k as usize; 188 assert!(ku < values.len()-1); 189 arr[j] = values[ku] + (c*n - (k as f32)) * (values[ku+1] - values[ku]); 190 } 191 SFilterDataComponent::Discrete(_) => { 192 let n = values.len() as f32; 193 let k = (n * c).floor() as usize; 194 assert!(k < values.len()); 195 arr[j] = values[k]; 196 } 197 SFilterDataComponent::Identity | 198 SFilterDataComponent::Linear(_,_) | 199 SFilterDataComponent::Gamma(_,_,_) => { 200 unreachable!(); 201 } 202 } 203 204 } 205 } 206 207 writer.push_one(arr); 208 } 209 } 210 SFilterDataComponent::Linear(a, b) => { 211 writer.push_one([*a, *b, 0.0, 0.0]); 212 } 213 SFilterDataComponent::Gamma(a, b, c) => { 214 writer.push_one([*a, *b, *c, 0.0]); 215 } 216 } 217 }