Source code

Revision control

Other Tools

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::gpu_cache::{GpuCacheHandle};
7
use crate::frame_builder::FrameBuildingState;
8
use crate::gpu_cache::GpuDataRequest;
9
use crate::intern;
10
use api::{FilterDataIntern, ComponentTransferFuncType};
11
12
13
pub type FilterDataHandle = intern::Handle<FilterDataIntern>;
14
15
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
16
#[cfg_attr(feature = "capture", derive(Serialize))]
17
#[cfg_attr(feature = "replay", derive(Deserialize))]
18
pub enum SFilterDataComponent {
19
Identity,
20
Table(Vec<f32>),
21
Discrete(Vec<f32>),
22
Linear(f32, f32),
23
Gamma(f32, f32, f32),
24
}
25
26
impl Eq for SFilterDataComponent {}
27
28
impl hash::Hash for SFilterDataComponent {
29
fn hash<H: hash::Hasher>(&self, state: &mut H) {
30
match self {
31
SFilterDataComponent::Identity => {
32
0.hash(state);
33
}
34
SFilterDataComponent::Table(values) => {
35
1.hash(state);
36
values.len().hash(state);
37
for val in values {
38
val.to_bits().hash(state);
39
}
40
}
41
SFilterDataComponent::Discrete(values) => {
42
2.hash(state);
43
values.len().hash(state);
44
for val in values {
45
val.to_bits().hash(state);
46
}
47
}
48
SFilterDataComponent::Linear(a, b) => {
49
3.hash(state);
50
a.to_bits().hash(state);
51
b.to_bits().hash(state);
52
}
53
SFilterDataComponent::Gamma(a, b, c) => {
54
4.hash(state);
55
a.to_bits().hash(state);
56
b.to_bits().hash(state);
57
c.to_bits().hash(state);
58
}
59
}
60
}
61
}
62
63
impl SFilterDataComponent {
64
pub fn to_int(&self) -> u32 {
65
match self {
66
SFilterDataComponent::Identity => 0,
67
SFilterDataComponent::Table(_) => 1,
68
SFilterDataComponent::Discrete(_) => 2,
69
SFilterDataComponent::Linear(_, _) => 3,
70
SFilterDataComponent::Gamma(_, _, _) => 4,
71
}
72
}
73
74
pub fn from_functype_values(
75
func_type: ComponentTransferFuncType,
76
values: &[f32],
77
) -> SFilterDataComponent {
78
match func_type {
79
ComponentTransferFuncType::Identity => SFilterDataComponent::Identity,
80
ComponentTransferFuncType::Table => SFilterDataComponent::Table(values.to_vec()),
81
ComponentTransferFuncType::Discrete => SFilterDataComponent::Discrete(values.to_vec()),
82
ComponentTransferFuncType::Linear => SFilterDataComponent::Linear(values[0], values[1]),
83
ComponentTransferFuncType::Gamma => SFilterDataComponent::Gamma(values[0], values[1], values[2]),
84
}
85
}
86
}
87
88
#[derive(Debug, Clone, MallocSizeOf, PartialEq, Eq, Hash)]
89
#[cfg_attr(feature = "capture", derive(Serialize))]
90
#[cfg_attr(feature = "replay", derive(Deserialize))]
91
pub struct SFilterData {
92
pub r_func: SFilterDataComponent,
93
pub g_func: SFilterDataComponent,
94
pub b_func: SFilterDataComponent,
95
pub a_func: SFilterDataComponent,
96
}
97
98
#[derive(Debug, Clone, MallocSizeOf, PartialEq, Eq, Hash)]
99
#[cfg_attr(feature = "capture", derive(Serialize))]
100
#[cfg_attr(feature = "replay", derive(Deserialize))]
101
pub struct SFilterDataKey {
102
pub data: SFilterData,
103
}
104
105
impl intern::InternDebug for SFilterDataKey {}
106
107
#[derive(Debug)]
108
#[cfg_attr(feature = "capture", derive(Serialize))]
109
#[cfg_attr(feature = "replay", derive(Deserialize))]
110
#[derive(MallocSizeOf)]
111
pub struct SFilterDataTemplate {
112
pub data: SFilterData,
113
pub gpu_cache_handle: GpuCacheHandle,
114
}
115
116
impl From<SFilterDataKey> for SFilterDataTemplate {
117
fn from(item: SFilterDataKey) -> Self {
118
SFilterDataTemplate {
119
data: item.data,
120
gpu_cache_handle: GpuCacheHandle::new(),
121
}
122
}
123
}
124
125
impl SFilterData {
126
pub fn is_identity(&self) -> bool {
127
self.r_func == SFilterDataComponent::Identity
128
&& self.g_func == SFilterDataComponent::Identity
129
&& self.b_func == SFilterDataComponent::Identity
130
&& self.a_func == SFilterDataComponent::Identity
131
}
132
133
pub fn update(&self, mut request: GpuDataRequest) {
134
push_component_transfer_data(&self.r_func, &mut request);
135
push_component_transfer_data(&self.g_func, &mut request);
136
push_component_transfer_data(&self.b_func, &mut request);
137
push_component_transfer_data(&self.a_func, &mut request);
138
assert!(!self.is_identity());
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 update(
148
&mut self,
149
frame_state: &mut FrameBuildingState,
150
) {
151
if let Some(request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) {
152
self.data.update(request);
153
}
154
}
155
}
156
157
impl intern::Internable for FilterDataIntern {
158
type Key = SFilterDataKey;
159
type StoreData = SFilterDataTemplate;
160
type InternData = ();
161
}
162
163
fn push_component_transfer_data(
164
func_comp: &SFilterDataComponent,
165
request: &mut GpuDataRequest,
166
) {
167
match func_comp {
168
SFilterDataComponent::Identity => {}
169
SFilterDataComponent::Table(values) |
170
SFilterDataComponent::Discrete(values) => {
171
// Push a 256 entry lookup table.
172
assert!(values.len() > 0);
173
for i in 0 .. 64 {
174
let mut arr = [0.0 ; 4];
175
for j in 0 .. 4 {
176
if (values.len() == 1) || (i == 63 && j == 3) {
177
arr[j] = values[values.len()-1];
178
} else {
179
let c = ((4*i + j) as f32)/255.0;
180
match func_comp {
181
SFilterDataComponent::Table(_) => {
182
let n = (values.len()-1) as f32;
183
let k = (n * c).floor() as u32;
184
let ku = k as usize;
185
assert!(ku < values.len()-1);
186
arr[j] = values[ku] + (c*n - (k as f32)) * (values[ku+1] - values[ku]);
187
}
188
SFilterDataComponent::Discrete(_) => {
189
let n = values.len() as f32;
190
let k = (n * c).floor() as usize;
191
assert!(k < values.len());
192
arr[j] = values[k];
193
}
194
SFilterDataComponent::Identity |
195
SFilterDataComponent::Linear(_,_) |
196
SFilterDataComponent::Gamma(_,_,_) => {
197
unreachable!();
198
}
199
}
200
201
}
202
}
203
204
request.push(arr);
205
}
206
}
207
SFilterDataComponent::Linear(a, b) => {
208
request.push([*a, *b, 0.0, 0.0]);
209
}
210
SFilterDataComponent::Gamma(a, b, c) => {
211
request.push([*a, *b, *c, 0.0]);
212
}
213
}
214
}