diff --git a/core/dr-gpu/examples/sweep.rs b/core/dr-gpu/examples/sweep.rs index 9f6884a..9327bc9 100644 --- a/core/dr-gpu/examples/sweep.rs +++ b/core/dr-gpu/examples/sweep.rs @@ -182,8 +182,7 @@ fn render_to( // and the example never has to know which it was handed. let shader = graph.compose_for(ColourSpace::Srgb); let scale = graph.render_scale(image.size(), (w, h)); - let detail = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); + let detail = graph.compose_detail(scale.full_size(), scale.render_size()); let key = graph.invalidation().through(Affects::Colour); adjust .render_detailed(image, &shader, w, h, None, &detail, key) diff --git a/core/dr-gpu/src/adjust.rs b/core/dr-gpu/src/adjust.rs index 7aa9d95..100d124 100644 --- a/core/dr-gpu/src/adjust.rs +++ b/core/dr-gpu/src/adjust.rs @@ -122,6 +122,8 @@ pub struct AdjustPass { colour_dispatches: usize, /// Detail dispatches encoded. detail_dispatches: usize, + /// View passes encoded — one per render with a detail stage (D19). + view_dispatches: usize, } struct Target { @@ -653,6 +655,7 @@ impl AdjustPass { sample: SampleCache::new(ctx), colour_dispatches: 0, detail_dispatches: 0, + view_dispatches: 0, } } @@ -1048,13 +1051,14 @@ impl AdjustPass { /// Render one frame with a neighbourhood stage. /// /// `shader` and `detail` must be the two halves of **one** composition — - /// `EditGraph::compose_for` and `EditGraph::compose_detail_for` on the same - /// graph, at the same output space. The fused pass stops at linear working - /// values when a detail stage exists and the last detail pass performs the - /// output transform, so a mismatched pair either encodes twice or not at - /// all. + /// `EditGraph::compose_for` and `EditGraph::compose_detail` on the same + /// graph. The fused pass stops at linear working values when a detail + /// stage exists, and its view pass ([`ComposedShader::view`]) performs the + /// view transform and the output transform after the last detail pass + /// (D19), so a mismatched pair either encodes twice or not at all. /// - /// An empty `detail` falls through to [`Self::render_masked`], which is + /// An encoded shader with an empty `detail` falls through to + /// [`Self::render_masked`], which is /// the honest thing to do rather than an optimisation: an edit with no /// active sharpening *is* an ordinary edit, and it should cost exactly /// what one costs. @@ -1094,17 +1098,25 @@ impl AdjustPass { detail: &ComposedDetail, colour_key: u64, ) -> Result<&wgpu::Texture, GpuError> { - if detail.is_empty() { + // An edit with no detail stage encodes in the fused pass, and is an + // ordinary render. Decided from the shader rather than from the chain: + // an active kernel too fine for this render emits no pass, and its + // fused pass has still stopped at linear values for the view pass. + if shader.output_mode == OutputMode::Encoded && detail.is_empty() { return self.render_masked(source, shader, width, height, masks); } - if shader.output_mode != OutputMode::LinearWorking { - return Err(GpuError::ShaderCompilation( - "this detail chain expects a fused pass composed to hand on \ - linear working values, but the shader given encodes its own \ - output; compose both halves from the same graph" - .into(), - )); - } + let view = match (shader.output_mode, shader.view.as_deref()) { + (OutputMode::LinearWorking, Some(view)) => view, + _ => { + return Err(GpuError::ShaderCompilation( + "this detail chain expects a fused pass composed to hand on \ + linear working values, with its view pass, but the shader \ + given encodes its own output; compose both halves from the \ + same graph" + .into(), + )); + } + }; let (width, height) = (width.max(1), height.max(1)); self.ensure_target(width, height); @@ -1117,6 +1129,7 @@ impl AdjustPass { // both want `&mut self`, and the second holds its borrow across the // encode below. self.pipeline(shader)?; + self.pipeline(view)?; let colour_view = self .detail .colour_target(detail.len(), width, height) @@ -1207,20 +1220,12 @@ impl AdjustPass { self.colour_dispatches += 1; } - // One encoder for the colour pass and every detail pass, submitted - // once — the shape `MaskPass::render` established. Submission order is - // the whole of the synchronisation: each pass reads what the previous - // one wrote, through the same queue. - let target_view = self.targets[self.current] - .as_ref() - .expect("ensured above") - .view - .clone(); - let ran = match self - .detail - .encode(&mut enc, detail, &target_view, width, height) - { - Ok(ran) => ran, + // One encoder for the colour pass, every detail pass and the view pass, + // submitted once — the shape `MaskPass::render` established. + // Submission order is the whole of the synchronisation: each pass + // reads what the previous one wrote, through the same queue. + let (ran, result) = match self.detail.encode(&mut enc, detail, width, height) { + Ok(done) => done, Err(e) => { // Nothing is submitted, so a cache this frame was to write // holds nothing, and must not be read as though it did. @@ -1230,6 +1235,86 @@ impl AdjustPass { return Err(e); } }; + + // TRACES: FR-DEV-3j + // The view pass: the view transform and the output transform, after + // every kernel (D19). Its own uniform block, filled from the source + // like the fused pass's — it reads the non-linear flag and the film + // settings there — with the sample cache off, because the colour it + // reads is the detail stage's result, bound where the cache would be. + let view_uniforms = Self::fused_uniforms(source, view); + let view_params = self + .ctx + .device + .create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("adjust-view-params"), + contents: bytemuck::cast_slice(&view_uniforms), + usage: wgpu::BufferUsages::UNIFORM, + }); + let (_, no_sample_out) = self.sample.views(SampleUse::Direct); + let target_view = self.targets[self.current] + .as_ref() + .expect("ensured above") + .view + .clone(); + let view_bind_group = self + .ctx + .device + .create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("adjust-view-bg"), + layout: &self.bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(source.view()), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: view_params.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(&target_view), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::TextureView( + masks.map_or(&self.empty_masks, |m| m.view()), + ), + }, + wgpu::BindGroupEntry { + binding: 4, + resource: wgpu::BindingResource::TextureView(&film_curves), + }, + wgpu::BindGroupEntry { + binding: 5, + resource: wgpu::BindingResource::TextureView(&film_lut), + }, + wgpu::BindGroupEntry { + binding: 6, + resource: wgpu::BindingResource::TextureView(&result), + }, + wgpu::BindGroupEntry { + binding: 7, + resource: wgpu::BindingResource::TextureView(&no_sample_out), + }, + ], + }); + { + let pipeline = self + .cache + .get(&view.structure_hash) + .expect("compiled above"); + let mut pass = enc.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("adjust-view-pass"), + timestamp_writes: None, + }); + pass.set_pipeline(pipeline); + pass.set_bind_group(0, &view_bind_group, &[]); + pass.dispatch_workgroups(width.div_ceil(8), height.div_ceil(8), 1); + } + self.view_dispatches += 1; + self.ctx.queue.submit(Some(enc.finish())); self.detail_dispatches += ran; self.colour_key = Some((key, width, height)); @@ -1378,6 +1463,13 @@ impl AdjustPass { self.detail_dispatches } + /// TRACES: FR-DEV-3j + /// View passes encoded since this pass was created: one for every render + /// that had a detail stage, since the view transform follows it. + pub fn view_dispatches(&self) -> usize { + self.view_dispatches + } + /// How many linear intermediates have been allocated. For tests: see /// [`crate::MaskPass::allocations`] for the regression this catches. pub fn detail_allocations(&self) -> usize { @@ -2351,7 +2443,7 @@ mod tests { // find those operations in neither stage and fail for a reason that is // not a defect. Shadows the smaller size deliberately. let (w, h) = g.output_size(512, 512); - let detail = g.compose_detail_for((512, 512), (w, h), dr_types::ColourSpace::Srgb); + let detail = g.compose_detail((512, 512), (w, h)); assert!( !detail.is_empty(), "the detail half composed nothing, so nothing of it was compiled" diff --git a/core/dr-gpu/src/detail.rs b/core/dr-gpu/src/detail.rs index 14553b3..b22e2a7 100644 --- a/core/dr-gpu/src/detail.rs +++ b/core/dr-gpu/src/detail.rs @@ -43,12 +43,12 @@ //! dispatch is skipped, and dragging a sharpening slider costs the detail //! passes alone (FR-DEV-3d). //! -//! The remaining passes alternate between slots 1 and 2, and the last one -//! writes the display texture directly rather than an intermediate — so a -//! chain of *N* passes costs *N* dispatches and not *N* + 1, and there is no -//! resolve pass to pay for. That leaves the allocation at `1 + min(N-1, 2)` -//! textures: one for a single-pass operation, two for a separable blur, three -//! however long the chain gets after that. +//! The passes alternate between slots 1 and 2, the last one included: since +//! D19 it hands its result to the adjust pass's **view pass**, which performs +//! the view transform and the output transform after every kernel, so no +//! detail pass writes the display texture. A chain of *N* passes costs *N* +//! dispatches plus that one, and the allocation is `1 + min(N, 2)` textures. +//! An empty chain costs the view pass alone, reading slot 0. //! //! # The reduced chain, and why a second one was needed //! @@ -186,10 +186,9 @@ impl Intermediates { /// intermediate against a fresh colour result and never be told. pub(crate) struct DetailRunner { ctx: GpuContext, - /// Layout for a pass writing another linear intermediate. + /// Layout for every pass: each writes a linear intermediate, the last + /// one included, and the adjust pass's view pass reads the last (D19). to_linear: Layout, - /// Layout for the last pass, which writes the display texture. - to_output: Layout, /// Compiled pipelines by pass structure hash. cache: HashMap, pool: Intermediates, @@ -255,7 +254,6 @@ impl DetailRunner { Self { ctx: ctx.clone(), to_linear: Layout::new(ctx, INTERMEDIATE_FORMAT, "detail-linear"), - to_output: Layout::new(ctx, crate::AdjustPass::FORMAT, "detail-output"), cache: HashMap::new(), pool: Intermediates::new(), reduced: Intermediates::new(), @@ -274,27 +272,30 @@ impl DetailRunner { width: u32, height: u32, ) -> &wgpu::TextureView { - // One for the colour pass's result, then one per hand-off between - // detail passes, capped at two because a ping-pong needs no more: the - // last pass writes the display texture rather than an intermediate. - let needed = 1 + passes.saturating_sub(1).min(2); + // One for the colour pass's result, then one per pass, capped at two + // because a ping-pong needs no more. The last pass writes an + // intermediate like the others since D19 — the view pass reads it — + // so a one-pass chain needs two slots where it used to need one. + let needed = 1 + passes.min(2); self.pool.ensure(&self.ctx, needed, width, height); &self.pool.slots[0].view } - /// Encode every pass of `chain`, the last one writing `output`. + /// Encode every pass of `chain`, and return how many ran and the view + /// the last one wrote — slot 0, the colour pass's own result, for an + /// empty chain. /// /// The caller must already have run the fused colour pass into /// [`Self::colour_target`] — or established that a previous frame's is - /// still valid, which is the whole point of keeping slot 0. + /// still valid, which is the whole point of keeping slot 0 — and reads the + /// returned view in the view pass that finishes the render (D19). pub(crate) fn encode( &mut self, encoder: &mut wgpu::CommandEncoder, chain: &ComposedDetail, - output: &wgpu::TextureView, width: u32, height: u32, - ) -> Result { + ) -> Result<(usize, wgpu::TextureView), GpuError> { for pass in &chain.passes { self.compile(pass)?; } @@ -340,17 +341,15 @@ impl DetailRunner { for pass in chain.passes.iter() { let scaled = pass.output_scale > 1; - // The last pass carries the output transform into the display - // texture, which is the render size by definition. A scaled pass - // there would bind a shader dispatching over a quarter-size grid - // to a full-size target and write a quarter of the picture — a - // wrong image rather than a validation failure, so it is caught - // here and named. - if scaled && pass.writes_output { + // The last pass hands the view pass its input, which is read at + // the render size by definition. A scaled pass there would leave + // the result in the reduced chain and the view pass would read the + // full-size slot before it — a wrong image rather than a + // validation failure, so it is caught here and named. + if scaled && std::ptr::eq(pass, chain.passes.last().expect("iterating")) { return Err(GpuError::ShaderCompilation(format!( "detail pass {} declares output_scale {} and is last in \ - the chain; the output transform is written at the render \ - size", + the chain; the view pass reads the render size", pass.label, pass.output_scale ))); } @@ -365,17 +364,14 @@ impl DetailRunner { }; // Read what the previous pass in *this pass's own chain* wrote; - // write the next slot of it, or the display texture if this is the - // last pass. Alternating slots is what stops a pass reading the + // write the next slot of it. Alternating slots is what stops a pass reading the // texture it is writing — on a compute pass that is not an error // the driver reports, merely a picture that depends on scheduling. let source = match (scaled, carried) { (true, Some(slot)) => &self.reduced.slots[slot].view, _ => &self.pool.slots[full].view, }; - let destination = if pass.writes_output { - output - } else if scaled { + let destination = if scaled { &self.reduced.slots[reduced_writes % 2].view } else { &self.pool.slots[1 + (full_writes % 2)].view @@ -387,11 +383,7 @@ impl DetailRunner { Some(slot) => &self.reduced.slots[slot].view, None => &self.no_reduced, }; - let layout = if pass.writes_output { - &self.to_output - } else { - &self.to_linear - }; + let layout = &self.to_linear; let params = self .ctx @@ -464,9 +456,7 @@ impl DetailRunner { compute.dispatch_workgroups(dispatch_w.div_ceil(8), dispatch_h.div_ceil(8), 1); drop(compute); - if pass.writes_output { - // Nothing downstream to hand anything to. - } else if scaled { + if scaled { carried = Some(reduced_writes % 2); reduced_writes += 1; } else { @@ -480,7 +470,7 @@ impl DetailRunner { } } - Ok(chain.passes.len()) + Ok((chain.passes.len(), self.pool.slots[full].view.clone())) } /// Compile one pass, or leave the cached pipeline in place. @@ -508,11 +498,7 @@ impl DetailRunner { source: wgpu::ShaderSource::Wgsl(pass.source.as_str().into()), }); - let layout = if pass.writes_output { - &self.to_output - } else { - &self.to_linear - }; + let layout = &self.to_linear; let pipeline = self .ctx diff --git a/core/dr-gpu/tests/capture_sharpen.rs b/core/dr-gpu/tests/capture_sharpen.rs index eebf7e8..dfdd36b 100644 --- a/core/dr-gpu/tests/capture_sharpen.rs +++ b/core/dr-gpu/tests/capture_sharpen.rs @@ -87,8 +87,7 @@ fn sharpened(amount: f32, radius: f32, threshold: f32) -> EditGraph { fn render(pass: &mut AdjustPass, graph: &EditGraph, source: &DemosaicedImage, out: u32) -> Vec { let shader = graph.compose_for(ColourSpace::Srgb); let scale = graph.render_scale(source.size(), (out, out)); - let detail = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); + let detail = graph.compose_detail(scale.full_size(), scale.render_size()); let key = graph.invalidation().through(Affects::Colour); pass.render_detailed(source, &shader, out, out, None, &detail, key) .expect("render"); @@ -413,7 +412,7 @@ fn dragging_the_amount_recompiles_nothing_and_reallocates_nothing() { let pipelines = pass.cached_detail_pipelines(); let allocations = pass.detail_allocations(); assert_eq!(pipelines, 2, "one per axis of the separable mask"); - assert_eq!(allocations, 2, "the colour result, and one hand-off"); + assert_eq!(allocations, 3, "the colour result, and the ping-pong pair"); assert_eq!(pass.detail_dispatches(), 2); assert_eq!(pass.colour_dispatches(), 1); @@ -453,13 +452,12 @@ fn dragging_the_amount_recompiles_nothing_and_reallocates_nothing() { #[test] fn a_render_too_coarse_for_the_radius_still_reaches_the_screen() { - // The failure mode that the pass-through exists to prevent, proved on a - // device rather than argued about. With the radius finer than a render - // pixel the operation declines to sharpen — but it is still active, so the - // fused pass has already been composed to hand on unclipped linear values, - // and something must still perform the output transform. An empty chain - // here would not be a soft preview: it would be a hard error out of - // `render_detailed`, on the most ordinary develop view there is. + // Proved on a device rather than argued about. With the radius finer than + // a render pixel the operation declines to sharpen — but it is still + // active, so the fused pass has already been composed to hand on + // unclipped linear values, and something must still perform the output + // transform. Since D19 that is the view pass, whatever the chain holds: + // the chain is empty and the frame is still whole. let Some(ctx) = ctx() else { return }; const SOURCE: u32 = 128; const RENDER: u32 = 32; // a quarter scale, as a fit view of a large frame @@ -471,7 +469,16 @@ fn a_render_too_coarse_for_the_radius_still_reaches_the_screen() { let mut pass = AdjustPass::new(&ctx); let sharp = render(&mut pass, &graph, &source, RENDER); - assert_eq!(pass.detail_dispatches(), 1, "one pass, and it only encodes"); + assert_eq!( + pass.detail_dispatches(), + 0, + "nothing to sharpen at this scale" + ); + assert_eq!( + pass.view_dispatches(), + 1, + "and the view pass finishes the frame" + ); // And what reaches the screen is the unsharpened picture, not a black // frame, a linear one, or a guess. diff --git a/core/dr-gpu/tests/detail_instances.rs b/core/dr-gpu/tests/detail_instances.rs index c508995..9ca2475 100644 --- a/core/dr-gpu/tests/detail_instances.rs +++ b/core/dr-gpu/tests/detail_instances.rs @@ -38,15 +38,17 @@ fn grey(ctx: &GpuContext) -> DemosaicedImage { DemosaicedImage::from_rgba8(ctx, &data, SIZE, SIZE).expect("upload") } -/// A pass that sums the instance list into the red channel and writes the -/// output. Deliberately trivial: the value on screen is then a direct readout -/// of what arrived in the buffer. +/// A pass that sums the instance list into the red channel and writes a +/// linear intermediate, which the view pass then encodes (D19). Deliberately +/// trivial: the value on screen is then a direct readout of what arrived in the +/// buffer, through the sRGB encode — the source is an 8-bit upload, so the +/// view transform is skipped for it and the encode is the only thing between. fn summing_pass(storage: Vec<[f32; 4]>, structure: u64) -> ComposedDetailPass { let source = " @group(0) @binding(0) var source: texture_2d; struct Params { detail_base: vec4 } @group(0) @binding(1) var u: Params; -@group(0) @binding(2) var output: texture_storage_2d; +@group(0) @binding(2) var output: texture_storage_2d; @group(0) @binding(3) var instances: array>; @compute @workgroup_size(8, 8, 1) @@ -61,7 +63,7 @@ fn main(@builtin(global_invocation_id) gid: vec3) { for (var i = 0u; i < n; i = i + 1u) { total = total + instances[i].x * f32(i + 1u); } - textureStore(output, vec2(gid.xy), vec4(total, f32(n) / 255.0, 0.0, 1.0)); + textureStore(output, vec2(gid.xy), vec4(total, f32(n) * 0.1, 0.0, 1.0)); } " .to_string(); @@ -73,13 +75,17 @@ fn main(@builtin(global_invocation_id) gid: vec3) { uniforms: vec![SIZE as f32, SIZE as f32, 1.0, 0.0], storage, radius: 0, - writes_output: true, // Any distinct number: the hash is a cache key, and these tests are // what decide whether two chains share a pipeline. structure_hash: structure, } } +/// A linear value as the view pass leaves it in the 8-bit output. +fn encoded(linear: f32) -> u8 { + (dr_types::Transfer::Srgb.encode(linear) * 255.0).round() as u8 +} + fn render(pass: &mut AdjustPass, source: &DemosaicedImage, chain: &ComposedDetail) -> Vec { // The fused half has to be composed knowing a detail stage follows it, or // it encodes its own output and the chain would quantise twice — a mismatch @@ -118,12 +124,15 @@ fn a_pass_reads_the_list_it_was_given() { let pixels = render(&mut pass, &source, &chain); let (red, green) = (pixels[0], pixels[1]); - // 0.05·1 + 0.1·2 = 0.25, written straight to an rgba8 target. + // 0.05·1 + 0.1·2 = 0.25. assert!( - red.abs_diff((0.25 * 255.0) as u8) <= 1, + red.abs_diff(encoded(0.25)) <= 1, "the shader summed {red}, not the list it was handed" ); - assert_eq!(green, 2, "arrayLength saw both entries"); + assert!( + green.abs_diff(encoded(0.2)) <= 1, + "arrayLength saw both entries" + ); } /// A convolution declares no list and must still run: it is bound to the @@ -142,7 +151,10 @@ fn a_pass_with_no_list_still_runs() { let pixels = render(&mut pass, &source, &chain); assert_eq!(pixels[0], 0, "the placeholder is zeroed"); - assert_eq!(pixels[1], 1, "and is exactly one element long"); + assert!( + pixels[1].abs_diff(encoded(0.1)) <= 1, + "and is exactly one element long" + ); } /// The property that makes placing the tenth spot as cheap as moving a slider: diff --git a/core/dr-gpu/tests/detail_stage.rs b/core/dr-gpu/tests/detail_stage.rs index dd14be0..ff46533 100644 --- a/core/dr-gpu/tests/detail_stage.rs +++ b/core/dr-gpu/tests/detail_stage.rs @@ -101,8 +101,7 @@ fn render( let _ = ctx; let shader = graph.compose_for(ColourSpace::Srgb); let scale = graph.render_scale(source.size(), (out, out)); - let detail = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); + let detail = graph.compose_detail(scale.full_size(), scale.render_size()); let key = graph.invalidation().through(Affects::Colour); pass.render_detailed(source, &shader, out, out, None, &detail, key) .expect("render"); @@ -301,7 +300,7 @@ fn dragging_a_slider_recompiles_nothing_and_reallocates_nothing() { let pipelines = pass.cached_detail_pipelines(); let allocations = pass.detail_allocations(); assert_eq!(pipelines, 2, "one per pass of the separable blur"); - assert_eq!(allocations, 2, "the colour result, and one hand-off"); + assert_eq!(allocations, 3, "the colour result, and the ping-pong pair"); for radius in [0.06, 0.07, 0.08, 0.09] { graph.set_param(PROBE, RADIUS, radius); @@ -403,8 +402,7 @@ fn an_empty_chain_falls_through_to_the_ordinary_render() { let shader = graph.compose_for(ColourSpace::Srgb); let scale = graph.render_scale((SIZE, SIZE), (SIZE, SIZE)); - let detail = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); + let detail = graph.compose_detail(scale.full_size(), scale.render_size()); assert!(detail.is_empty()); pass.render_detailed(&source, &shader, SIZE, SIZE, None, &detail, 0) diff --git a/core/dr-gpu/tests/local_contrast.rs b/core/dr-gpu/tests/local_contrast.rs index 8ede8a8..7a63ab8 100644 --- a/core/dr-gpu/tests/local_contrast.rs +++ b/core/dr-gpu/tests/local_contrast.rs @@ -109,8 +109,7 @@ fn row_rgb(pixels: &[u8], size: u32, y: u32) -> Vec<[u8; 3]> { fn render(pass: &mut AdjustPass, graph: &EditGraph, source: &DemosaicedImage, out: u32) -> Vec { let shader = graph.compose_for(ColourSpace::Srgb); let scale = graph.render_scale(source.size(), (out, out)); - let detail = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); + let detail = graph.compose_detail(scale.full_size(), scale.render_size()); let key = graph.invalidation().through(Affects::Colour); pass.render_detailed(source, &shader, out, out, None, &detail, key) .expect("render"); @@ -683,28 +682,21 @@ fn texture_contributes_nothing_where_its_scale_does_not_exist() { // `render_masked`, and was rejected for handing a linear-working shader // to the plain path — so texture alone on a thumbnail did not render. // - // The seam was closed where that note said it would have to be, at the - // composition boundary: `compose_detail` now emits a bodyless - // `detail/resolve` pass in exactly this case, which reads only the pixel - // it writes and performs the output transform the fused pass declined to - // do. So the chain is no longer empty — it carries precisely the one pass - // that finishes the render and no kernel at all, which is the honest - // description of "a two-pixel surface structure is not present in a - // 128-pixel rendering". + // The seam was closed at the composition boundary, and closed again, + // more simply, by D19: no detail pass encodes any more, the fused pass's + // view pass performs the output transform whatever the chain holds, and + // so the empty chain is a whole render. That is the honest description of + // "a two-pixel surface structure is not present in a 128-pixel + // rendering". let scale = graph.render_scale(source.size(), (128, 128)); - let composed = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); - assert_eq!( - composed.len(), - 1, - "the chain must carry the resolve pass and nothing else" - ); - assert_eq!(composed.passes[0].label, "detail/resolve"); - assert_eq!( - composed.radius(), - 0, + let composed = graph.compose_detail(scale.full_size(), scale.render_size()); + assert!( + composed.is_empty(), "texture claimed a kernel it cannot draw" ); + let mut pass = AdjustPass::new(&ctx); + render(&mut pass, &graph, &source, 128); + assert_eq!(pass.view_dispatches(), 1, "the view pass still finishes it"); // With clarity on as well the edit is renderable again, and the dispatch // count says what the assertion above says: two passes, not four. Texture diff --git a/core/dr-gpu/tests/noise_reduction.rs b/core/dr-gpu/tests/noise_reduction.rs index 8952af2..becbd56 100644 --- a/core/dr-gpu/tests/noise_reduction.rs +++ b/core/dr-gpu/tests/noise_reduction.rs @@ -73,8 +73,7 @@ fn render_at( scale: RenderScale, ) -> Vec { let shader = graph.compose_for(ColourSpace::Srgb); - let detail = - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb); + let detail = graph.compose_detail(scale.full_size(), scale.render_size()); let key = graph.invalidation().through(Affects::Colour); pass.render_detailed(source, &shader, out.0, out.1, None, &detail, key) .expect("render"); diff --git a/core/dr-gpu/tests/spot_removal.rs b/core/dr-gpu/tests/spot_removal.rs index dba189e..c72c4ef 100644 --- a/core/dr-gpu/tests/spot_removal.rs +++ b/core/dr-gpu/tests/spot_removal.rs @@ -72,7 +72,7 @@ fn render(pass: &mut AdjustPass, graph: &EditGraph, source: &DemosaicedImage, ou let shader = graph.compose_for(ColourSpace::Srgb); let (w, h) = graph.output_size(source.size().0, source.size().1); let (w, h) = (w.min(out), h.min(out)); - let detail = graph.compose_detail_for(source.size(), (w, h), ColourSpace::Srgb); + let detail = graph.compose_detail(source.size(), (w, h)); let key = graph.invalidation().through(Affects::Colour); pass.render_detailed(source, &shader, w, h, None, &detail, key) .expect("render"); diff --git a/core/dr-gpu/tests/view_transform.rs b/core/dr-gpu/tests/view_transform.rs index af26321..77be72d 100644 --- a/core/dr-gpu/tests/view_transform.rs +++ b/core/dr-gpu/tests/view_transform.rs @@ -127,3 +127,52 @@ fn the_rendering_is_monotone_through_the_whole_range() { last = got; } } + +/// Render `graph` over a flat frame through `render_detailed`, the path every +/// frontend takes, and return the centre pixel's red. +fn rendered_detailed(ctx: &GpuContext, level: u16, graph: &EditGraph) -> (u8, AdjustPass) { + let source = Demosaicer::new(ctx) + .expect("demosaicer") + .run(&flat_raw(level)) + .expect("demosaic"); + let shader = graph.compose_for(dr_types::ColourSpace::Srgb); + let detail = graph.compose_detail(source.size(), (SIZE, SIZE)); + let key = graph.invalidation().through(dr_pipeline::Affects::Colour); + let mut adjust = AdjustPass::new(ctx); + adjust + .render_detailed(&source, &shader, SIZE, SIZE, None, &detail, key) + .expect("render"); + let (pixels, _, _) = adjust.export_pixels().expect("readback"); + let centre = ((SIZE / 2) * SIZE + SIZE / 2) * 4; + (pixels[centre as usize], adjust) +} + +#[test] +fn a_detail_stage_renders_through_the_view_pass_unchanged() { + // TRACES: FR-DEV-3j | FR-DEV-2 + // With a detail stage the view transform is a dispatch of its own after + // it (D19). Sharpening a flat field changes nothing, so the same frame + // with and without it must render the same: the view pass read the detail + // stage's result, applied the view transform once, and encoded once. + let Some(ctx) = ctx() else { + eprintln!("skipping: no GPU adapter"); + return; + }; + let plain = rendered(&ctx, 8_520, &EditGraph::default_chain()); + + let mut sharpened = EditGraph::default_chain(); + let id = dr_pipeline::ops::capture_sharpen::ID; + sharpened.set_param(id, dr_pipeline::ops::capture_sharpen::AMOUNT, 100.0); + sharpened.set_param(id, dr_pipeline::ops::capture_sharpen::RADIUS, 1.0); + let (detailed, pass) = rendered_detailed(&ctx, 8_520, &sharpened); + + assert!( + pass.detail_dispatches() > 0, + "the premise: a detail stage ran" + ); + assert_eq!(pass.view_dispatches(), 1); + assert!( + detailed.abs_diff(plain) <= 1, + "with a detail stage {detailed}, without {plain}" + ); +} diff --git a/core/dr-pipeline/src/detail.rs b/core/dr-pipeline/src/detail.rs index 1b3ee76..29cbb0e 100644 --- a/core/dr-pipeline/src/detail.rs +++ b/core/dr-pipeline/src/detail.rs @@ -122,8 +122,6 @@ use std::fmt::Write as _; -use dr_types::ColourSpace; - use crate::operation::{Helper, Operation, Uniform}; /// Floats the generated detail uniform block always carries, before an @@ -491,15 +489,6 @@ pub struct ComposedDetailPass { pub radius: u32, /// See [`DetailPass::output_scale`]. pub output_scale: u32, - /// Whether this pass writes the display/export texture rather than another - /// linear intermediate. - /// - /// True for exactly the last pass in the chain, which carries the output - /// transform — the primaries conversion, the clip and the encode that the - /// fused pass performs when there is no detail stage at all. Folding them - /// into the last pass rather than adding a resolve dispatch keeps the cost - /// of the stage at one dispatch per pass, not one plus one. - pub writes_output: bool, /// Identifies this pass's *structure*, for the pipeline cache. Covers the /// generated source, not the uniform values — so moving a slider uploads a /// buffer and reuses the compiled pipeline, exactly as the fused pass does. @@ -547,10 +536,11 @@ impl ComposedDetail { /// an edit with no sharpening produces an empty chain and `dr-gpu` runs the /// single dispatch it always did. /// -/// `output` is the space the **last** pass encodes into, and it is a parameter -/// for the same reason it is a parameter to [`crate::compose_with_framing`]: a -/// screen render and a Display P3 export are the same edit and different -/// shaders, and neither is more authoritative than the other. +/// No pass encodes. Every pass writes a linear intermediate, the last one +/// included, and the fused pass's view pass ([`crate::ComposedShader::view`]) +/// reads the last and performs the view transform and the output transform +/// (D19). So the output space is not a parameter here: a screen render and a +/// Display P3 export share one detail stage. /// /// # The generated uniform block /// @@ -562,12 +552,8 @@ impl ComposedDetail { /// is there because a two-pass operation emitting one body for both directions /// is a reasonable thing to want, and would otherwise need a uniform of its /// own purely to say which half it is in. -pub fn compose_detail( - ops: &[Box], - scale: RenderScale, - output: ColourSpace, -) -> ComposedDetail { - compose_detail_with(ops, &[], scale, output) +pub fn compose_detail(ops: &[Box], scale: RenderScale) -> ComposedDetail { + compose_detail_with(ops, &[], scale) } /// TRACES: FR-DEV-8 @@ -592,7 +578,6 @@ pub fn compose_detail_with( ops: &[Box], spots: &[DetailPass], scale: RenderScale, - output: ColourSpace, ) -> ComposedDetail { // Every pass of every active detail operation, flattened, carrying the // operation it came from for the uniform prefix and the helper set. @@ -624,45 +609,13 @@ pub fn compose_detail_with( } } - // An active detail operation that emitted nothing at this scale. - // - // Legal, and the honest answer for an acutance operation on a heavy proxy - // — a one-source-pixel radius is a third of a render pixel there and no - // kernel represents a third of a pixel (see [`RenderScale`]). But it opens - // a hole between the two halves of the composition: [`compose_full`] - // decides to hand on linear working values from the *operations*, which it - // must, having no scale to consult, so the fused pass has already stopped - // short of the output transform. Returning an empty chain here would leave - // that transform undone and bind an `rgba16float` shader to an - // `rgba8unorm` target, which surfaces as a wgpu validation failure a long - // way from the cause. - // - // So the chain is never empty when the fused pass is expecting one: a - // single pass with no body, which reads the intermediate and performs the - // output transform the fused pass skipped. One dispatch, in the uncommon - // case where a photographer has a kernel switched on at a scale that - // cannot draw it — against the alternative of the preview failing outright - // or `compose_full` growing a resolution argument it has no other use for. - if planned.is_empty() && ops.iter().any(|o| o.is_active() && o.detail().is_some()) { - return ComposedDetail { - passes: vec![compose_one( - RESOLVE_ID, - &[], - &DetailPass { - output_scale: 1, - label: "resolve", - radius: 0, - wgsl: String::new(), - uniforms: Vec::new(), - storage: Vec::new(), - }, - 0, - scale, - output, - true, - )], - }; - } + // An active detail operation may emit nothing at this scale — an + // acutance operation on a heavy proxy, whose one-source-pixel radius is a + // third of a render pixel (see [`RenderScale`]). The chain is then empty + // while the fused pass has stopped at linear working values, and that is + // fine: the fused pass's view pass reads the fused result directly and + // performs the output transform. Before D19 the last detail pass encoded, + // and this case needed a body-less resolve pass to do it. // TRACES: NFR-P5 // A pass whose body is empty changes nothing but where the pixels are: it @@ -674,12 +627,10 @@ pub fn compose_detail_with( // 2560 x 1600 frame on the reference laptop with its clocks held down. // // Dropped here, where the chain is still a list, and only where dropping - // it is exact: + // it is exact. The last pass is no exception since D19: it writes an + // `rgba16float` intermediate like the others, and the view pass reads + // whichever one the chain last wrote. // - // - **Not the last pass.** The last pass performs the output transform on - // what it read from an `rgba16float` intermediate. Moving that transform - // onto the pass before would apply it to that pass's `f32` result - // instead, which is a different rounding of the same picture. // - **Not after a reduced pass.** A full-resolution pass ends the reduced // chain (see `DetailRunner::encode`), so one that follows a scaled pass // is what stops the next operation reading the last one's base. None of @@ -688,45 +639,29 @@ pub fn compose_detail_with( // Everywhere else the pass before and the pass after exchange the same // `rgba16float` texels either way, `aux` included. let mut kept: Vec<(&str, &[Helper], DetailPass, usize)> = Vec::with_capacity(planned.len()); - let total = planned.len(); - for (position, entry) in planned.into_iter().enumerate() { + for entry in planned { let after_full = kept.last().is_none_or(|(_, _, p, _)| p.output_scale <= 1); - let droppable = position + 1 < total && after_full && entry.2.is_identity(); + let droppable = after_full && entry.2.is_identity(); if !droppable { kept.push(entry); } } let planned = kept; - let last = planned.len().saturating_sub(1); let passes = planned .into_iter() - .enumerate() - .map(|(position, (id, helpers, pass, index))| { - compose_one(id, helpers, &pass, index, scale, output, position == last) - }) + .map(|(id, helpers, pass, index)| compose_one(id, helpers, &pass, index, scale)) .collect(); ComposedDetail { passes } } -/// The operation id the resolve pass is labelled with. -/// -/// Not an operation: no `ops/*.yaml` declares it and nothing in the chain -/// answers to it. It exists so the generated label reads `detail/resolve` -/// rather than borrowing the id of whichever operation happened to fall -/// through, which would send a reader looking for a bug in that operation. -const RESOLVE_ID: &str = "detail"; - -#[allow(clippy::too_many_arguments)] fn compose_one( id: &str, helpers: &[Helper], pass: &DetailPass, index: usize, scale: RenderScale, - output: ColourSpace, - writes_output: bool, ) -> ComposedDetailPass { let prefix = format!("{}_{index}", crate::operation::sanitise(id)); @@ -772,41 +707,13 @@ fn compose_one( let _ = writeln!(helper_src, "{}\n", h.source.trim_end()); } - // The storage format and the tail are the *only* difference between an - // intermediate pass and the final one. Everything above — the taps, the - // uniforms, the body — is identical, which is what lets an operation write - // one kernel without knowing whether it happens to be last in the chain. - let (store_format, tail) = if writes_output { - ( - "rgba8unorm", - format!( - "{} // Clip to the output gamut and encode. The one quantisation\n\ - \x20 // the pipeline performs (FR-DEV-2), and it is here rather than\n\ - \x20 // in the fused pass because this is now the last thing to run.\n\ - \x20 c = clamp(c, vec3(0.0), vec3(1.0));\n\ - \x20 textureStore(output, coord, vec4(encode_output(c), 1.0));", - crate::operation::primaries_conversion(output) - ), - ) - } else { - ( - "rgba16float", - " // Another linear intermediate: no clip and no encode, because\n\ - \x20 // the pass after this one still has to read real values.\n\ - \x20 //\n\ - \x20 // `aux` rides in alpha. A pass that never touches it hands on\n\ - \x20 // whatever it was given, so the lane costs an operation that\n\ - \x20 // does not want it exactly one copy of a value it already read.\n\ - \x20 textureStore(output, coord, vec4(c, aux));" - .to_string(), - ) - }; - - let encode_fn = if writes_output { - crate::operation::encode_output_fn(output) - } else { - String::new() - }; + // Every pass writes another linear intermediate: no clip and no encode, + // because the view pass after the last one still has to read real values + // (D19). `aux` rides in alpha. A pass that never touches it hands on + // whatever it was given, so the lane costs an operation that does not want + // it exactly one copy of a value it already read. + let store_format = "rgba16float"; + let tail = " textureStore(output, coord, vec4(c, aux));"; let label = format!("{id}/{}", pass.label); let indented = body @@ -823,7 +730,7 @@ fn compose_one( // way back to a coordinate. // // In: linear sRGB, scene-referred, **unclipped**, at render resolution. -// Out: {} +// Out: the same, for the next pass or for the view pass after the last. struct Params {{ {uniform_fields}}} @@ -907,7 +814,7 @@ fn reduced_at(coord: vec2) -> f32 {{ return mix(mix(s00, s10, f.x), mix(s01, s11, f.x), f.y); }} -{helper_src}{encode_fn} +{helper_src} @compute @workgroup_size(8, 8, 1) fn main(@builtin(global_invocation_id) gid: vec3) {{ let dims = textureDimensions(output); @@ -936,12 +843,7 @@ fn main(@builtin(global_invocation_id) gid: vec3) {{ {tail} }} -", - if writes_output { - "display-encoded, in the output space." - } else { - "linear sRGB, for the next pass." - }, +" ); let structure_hash = crate::operation::hash_source(&source); @@ -956,7 +858,6 @@ fn main(@builtin(global_invocation_id) gid: vec3) {{ // dispatch size and a declaration is data, which since FR-PLG-2 can // come from a file this build did not write. output_scale: pass.output_scale.max(1), - writes_output, structure_hash, } } @@ -1095,27 +996,19 @@ mod tests { // dispatch. An unedited photograph must not pay for a sharpener it is // not using. let ops = with_blur(0.0); - let composed = compose_detail( - &ops, - RenderScale::full((512, 512)), - dr_types::ColourSpace::Srgb, - ); + let composed = compose_detail(&ops, RenderScale::full((512, 512))); assert!(composed.is_empty()); assert_eq!(fused(&ops).output_mode, OutputMode::Encoded); } #[test] - fn a_separable_blur_becomes_two_passes_and_only_the_last_encodes() { - // The multi-pass case, which is the one the ping-pong exists for. The - // first pass writes a linear intermediate and the second writes the - // display texture — so the output transform happens exactly once, at - // the end, wherever the end happens to be. + fn a_separable_blur_becomes_two_passes_and_neither_encodes() { + // The multi-pass case, which is the one the ping-pong exists for. Both + // passes write linear intermediates, and the fused pass's view pass + // reads the second and performs the view transform and the output + // transform — so those happen exactly once, after every kernel (D19). let ops = with_blur(0.05); - let composed = compose_detail( - &ops, - RenderScale::full((512, 512)), - dr_types::ColourSpace::Srgb, - ); + let composed = compose_detail(&ops, RenderScale::full((512, 512))); assert_eq!(composed.len(), 2); let first = &composed.passes[0]; @@ -1123,13 +1016,16 @@ mod tests { assert_eq!(first.label, "detail_probe/horizontal"); assert_eq!(last.label, "detail_probe/vertical"); - assert!(!first.writes_output); - assert!(first.source.contains("texture_storage_2d Box { - let mut op = CaptureSharpen::new(); - op.set_param(capture_sharpen::AMOUNT, 60.0); - Box::new(op) - }; + // A pass with an empty body costs a render-sized read and write and + // changes no texel, so it goes — wherever it falls since D19, the last + // position included, because the last pass writes an intermediate like + // every other and the view pass reads whichever the chain last wrote. + // Built by hand, and run as a repair so it goes first: no operation + // emits one any more (capture sharpening at a scale too coarse to draw + // its radius used to, and now emits nothing). + use crate::ops::NoiseReduction; let chroma = || -> Box { Box::new(NoiseReduction::with_amounts(0.0, 60.0)) }; - // A 24 MP frame fitted to a panel: a one-source-pixel radius is a - // quarter of a render pixel. let scale = RenderScale::new((1500, 1000), (6000, 4000)); - let unresolved = sharpen().detail().expect("a detail stage").passes(scale); - assert!( - unresolved.len() == 1 && unresolved[0].is_identity(), - "the premise: sharpening at this scale is one pass that does nothing" - ); - let labels = |ops: &[Box]| -> Vec { - compose_detail(ops, scale, dr_types::ColourSpace::Srgb) + let nothing = DetailPass { + output_scale: 1, + label: "nothing", + radius: 0, + wgsl: "// `c` already holds this pixel.".to_string(), + uniforms: Vec::new(), + storage: Vec::new(), + }; + assert!(nothing.is_identity(), "the premise"); + let labels: Vec = + compose_detail_with(&[chroma()], std::slice::from_ref(¬hing), scale) .passes .iter() .map(|p| p.label.clone()) - .collect() - }; - - // First, ahead of the chroma passes: dropped. - let first = labels(&[sharpen(), chroma()]); + .collect(); assert_eq!( - first, + labels, [ "noise_reduction/chroma-horizontal", "noise_reduction/chroma-vertical" ] ); - // Last, after them: kept, and it is the pass that encodes. - let last = labels(&[chroma(), sharpen()]); - assert_eq!(last.len(), 3); - assert_eq!(last[2], "capture_sharpen/unresolved"); - // Alone: kept, because the fused pass stopped short and something has - // to finish the frame. - assert_eq!(labels(&[sharpen()]), ["capture_sharpen/unresolved"]); + // Alone: dropped too, and the chain is empty — the view pass + // finishes the frame. + assert!(compose_detail_with(&[], &[nothing], scale).is_empty()); } #[test] @@ -1325,11 +1196,7 @@ mod tests { // A pass that says nothing about `aux` hands on what it was given, // which is why the box blur below needs no knowledge of it. let ops = with_blur(0.05); - let composed = compose_detail( - &ops, - RenderScale::full((512, 512)), - dr_types::ColourSpace::Srgb, - ); + let composed = compose_detail(&ops, RenderScale::full((512, 512))); for pass in &composed.passes { assert!( @@ -1344,11 +1211,12 @@ mod tests { .contains("textureStore(output, coord, vec4(c, aux));"), "an intermediate must carry the lane to the pass after it" ); - // The last pass writes the display texture, whose alpha is opacity and - // not scratch space. Readable there, not written — which is the right - // way round, because the combining pass is the one that reads it. - assert!(composed.passes[1].writes_output); - assert!(!composed.passes[1].source.contains("vec4(c, aux)")); + // The last pass carries it too: since D19 it writes an intermediate + // for the view pass rather than the display texture, whose alpha is + // opacity. The view pass reads only the colour. + assert!(composed.passes[1] + .source + .contains("textureStore(output, coord, vec4(c, aux));")); } #[test] @@ -1357,11 +1225,7 @@ mod tests { // overwhelmingly common edit: no sharpening means no chain, which // means `dr-gpu` runs the single fused dispatch it always did. let ops = crate::ops::chain(); - let composed = compose_detail( - &ops, - RenderScale::full((64, 64)), - dr_types::ColourSpace::Srgb, - ); + let composed = compose_detail(&ops, RenderScale::full((64, 64))); assert!(composed.is_empty()); assert_eq!(composed.radius(), 0); } diff --git a/core/dr-pipeline/src/graph.rs b/core/dr-pipeline/src/graph.rs index bfebe94..2813bcd 100644 --- a/core/dr-pipeline/src/graph.rs +++ b/core/dr-pipeline/src/graph.rs @@ -956,42 +956,31 @@ impl EditGraph { } /// TRACES: FR-DEV-3 | FR-DSP-1 - /// Generate the detail stage for this edit at one resolution, to sRGB. + /// Generate the detail stage for this edit at one resolution. /// /// Empty for every edit with no active neighbourhood operation, which is /// almost all of them — and in that case [`Self::compose`] emits the /// single encoded dispatch it always has. - pub fn compose_detail( - &self, - source: (u32, u32), - render: (u32, u32), - ) -> crate::detail::ComposedDetail { - self.compose_detail_for(source, render, dr_types::ColourSpace::Srgb) - } - - /// TRACES: FR-EXP-2 - /// The detail stage, encoded into a chosen output space. /// - /// The space belongs here as well as on [`Self::compose_for`] because when - /// a detail stage exists it is the *last* pass that performs the output - /// transform — the fused pass stops at linear working values. Composing - /// the two halves for different spaces would encode the edit twice, or - /// not at all. + /// No output space: since D19 no detail pass encodes. The fused pass's + /// view pass reads what the last one wrote and performs the view transform + /// and the output transform, so it is [`Self::compose_for`] alone that + /// names the space. + /// /// `source` is the demosaiced image's size and `render` the size being /// drawn. The scale is worked out here rather than handed in, because the /// repairs need the *source* size as well — a spot is stored in normalised /// source coordinates and has to be put through the framing to find out /// where it lands on this render, and a [`crate::detail::RenderScale`] /// describes the region on screen rather than the photograph. - pub fn compose_detail_for( + pub fn compose_detail( &self, source: (u32, u32), render: (u32, u32), - output: dr_types::ColourSpace, ) -> crate::detail::ComposedDetail { let scale = self.render_scale(source, render); let spots = self.spots.passes(&self.framing, source, scale); - crate::detail::compose_detail_with(&self.ops, &spots, scale, output) + crate::detail::compose_detail_with(&self.ops, &spots, scale) } /// TRACES: FR-DEV-3d diff --git a/core/dr-pipeline/src/operation.rs b/core/dr-pipeline/src/operation.rs index b389fc4..b882dda 100644 --- a/core/dr-pipeline/src/operation.rs +++ b/core/dr-pipeline/src/operation.rs @@ -562,6 +562,17 @@ pub struct ComposedShader { /// the interpolating paths, whose sample is a blend of four texels and /// not representable exactly in the source's own format. pub sample_key: Option, + /// TRACES: FR-DEV-3j + /// The view pass, for a shader that stops at [`OutputMode::LinearWorking`]. + /// + /// The view transform runs after the detail stage (D19): a sharpener or + /// a blur must convolve scene-linear values, not a display rendering. So + /// when a detail stage follows, this shader stops short of the view + /// transform, and this second shader — the same prologue for the + /// positions a fragment reads, the colour taken from the detail stage's + /// result bound as `sampled`, then the view transform and the output + /// transform — writes the display texture. `None` for every other mode. + pub view: Option>, } /// Fields the generated uniform struct always carries, before op uniforms. @@ -700,7 +711,7 @@ pub fn compose_full_revealing( reveal: Option<&crate::mask::Reveal>, ) -> ComposedShader { compose_inner( - ops, framing, output, masks, spots, warps, reveal, None, false, + ops, framing, output, masks, spots, warps, reveal, None, false, false, ) } @@ -770,6 +781,7 @@ fn compose_camera_tap( None, Some(OutputMode::CameraLinear), smooth, + false, ) } @@ -784,6 +796,7 @@ fn compose_inner( reveal: Option<&crate::mask::Reveal>, forced: Option, smooth: bool, + view_pass: bool, ) -> ComposedShader { // The lens corrections, composed into one coordinate transform. Beside // `framing` because they are the other half of the same stage: framing @@ -819,13 +832,22 @@ fn compose_inner( // sense above: `compose_camera_probe` is the only function that passes // it, with an empty operation list, and the mode it forces has its own // storage format and its own render entry on the GPU side. - let output_mode = forced.unwrap_or( - if ops.iter().any(|o| o.is_active() && o.detail().is_some()) || !spots.is_neutral() { - OutputMode::LinearWorking - } else { - OutputMode::Encoded - }, - ); + // + // TRACES: FR-DEV-3j + // The view pass is the other exception. It follows the detail stage and + // writes the display texture, so it is `Encoded` whatever the chain holds: + // it exists only because a detail stage does. + let output_mode = if view_pass { + OutputMode::Encoded + } else { + forced.unwrap_or( + if ops.iter().any(|o| o.is_active() && o.detail().is_some()) || !spots.is_neutral() { + OutputMode::LinearWorking + } else { + OutputMode::Encoded + }, + ) + }; // Whether an operation has taken over the rendering. Decided from the // operations for the same reason `output_mode` is: a caller that got it @@ -862,6 +884,11 @@ fn compose_inner( // Whether the composer emits a view transform — which is every render but // the camera-space tap and one a rendering operation has taken over. let views = !op_renders && output_mode != OutputMode::CameraLinear; + // And whether *this* shader is where it goes. Not the fused pass when a + // detail stage follows: the view transform maps into a display range, and + // a sharpener handed a display range is what D19 set out to stop. The + // view pass after the detail stage carries it instead. + let views_here = views && output_mode == OutputMode::Encoded; // Framing's block follows the base one at a fixed offset, for the same // reason: the prologue is emitted whether or not any operation is active, @@ -917,7 +944,7 @@ fn compose_inner( // none — `compose(&[])` in a test, or a probe. Absent altogether where // nothing is to be rendered: see `views`. let default_view = crate::ops::ViewTransform::new(); - let view: Option<&dyn Operation> = views.then(|| { + let view: Option<&dyn Operation> = views_here.then(|| { point(Stage::View) .next() .unwrap_or(&default_view as &dyn Operation) @@ -930,12 +957,17 @@ fn compose_inner( Matrix, Orphans, } - let steps = point(Stage::Camera) - .map(Step::Op) - .chain(std::iter::once(Step::Matrix)) - .chain(point(Stage::Scene).map(Step::Op)) - .chain(std::iter::once(Step::Orphans)) - .chain(view.map(Step::Op)); + // + // The view pass holds the view transform and nothing else: everything + // before it has already run, in the fused pass and the detail stage. + let mut steps: Vec = Vec::new(); + if !view_pass { + steps.extend(point(Stage::Camera).map(Step::Op)); + steps.push(Step::Matrix); + steps.extend(point(Stage::Scene).map(Step::Op)); + steps.push(Step::Orphans); + } + steps.extend(view.map(Step::Op)); for step in steps { let op = match step { @@ -1021,7 +1053,15 @@ fn compose_inner( // rather than among the operations — see `mask::LayerShader::reveal`. // Empty for every composition nobody is looking at a mask through, which // is all of them but the screen's. - let reveal_block = layers.reveal.clone(); + // + // And after the detail stage, when there is one: on the linear + // intermediate a flat tint would be sharpened and then rendered as some + // other colour. So it rides on whichever shader writes the display. + let reveal_block = if output_mode == OutputMode::Encoded { + layers.reveal.clone() + } else { + String::new() + }; uniform_fields.push_str(&layers.uniform_fields); uniform_values.extend_from_slice(&layers.uniform_values); for h in &layers.helpers { @@ -1157,6 +1197,70 @@ fn compose_inner( // Formatted with Rust's `Display` so the shader reads the same threshold // the probe checks against; see `CLIP_ONSET`. let clip_onset = CLIP_ONSET; + + // What the operations are handed. For the fused pass, the source texel + // made linear and balanced as shot; for the view pass, the scene as the + // detail stage left it, which is already all of that. + let head = if view_pass { + " // The view pass (FR-DEV-3j): everything up to the view transform ran + // in the fused pass and the detail stage, and what they left is in the + // texture bound as `sampled`, at this pixel. The prologue above ran only + // for the positions it publishes — `source_px` for a film's grain, and + // the corners it blacks out — and its colour is discarded. + let non_linear = u.as_shot_wb.w > 0.5; + c = textureLoad(sampled, vec2(gid.xy), 0).rgb; +" + .to_string() + } else { + format!( + " // A non-linear source is already display-encoded; undo that so the + // operations below see linear colour whatever the source was. + let non_linear = u.as_shot_wb.w > 0.5; + if (non_linear) {{ + c = decode_srgb(c); + }} + + // As-shot white balance. Applied unconditionally, before any operation, + // because it is part of *interpreting* the sensor rather than an edit: a + // Bayer sensor's green photosites collect far more signal than its red + // and blue, so raw camera-space values are strongly green and no amount + // of later correction recovers a neutral image from them. The white + // balance operation, when active, applies its own offset on top of this. + // + // A non-linear source has already had this applied in-camera; the uniform + // is neutral there, so this is a multiply by one rather than a branch. + // How close this pixel was to saturation before any balance was applied. + // A photosite at its white level carries no colour information — every + // channel simply stopped counting — so the balance below must not be + // allowed to tint it. + let clipped = smoothstep({clip_onset}, 1.0, max(c.r, max(c.g, c.b))); + + c = c * u.as_shot_wb.rgb; + + // **Highlight desaturation, and without it every blown sky is magenta.** + // + // A fully clipped pixel arrives as (1, 1, 1). The as-shot multipliers are + // not neutral — on a Canon 6D they are (1.93, 1.00, 1.68) — so balancing + // sends it to exactly that, and the camera matrix then produces R 2.88, + // G 0.51, B 2.03. Red and blue clip at one and green does not, which is + // magenta. The balance is correct; the input was not a colour. + // + // So a saturated pixel is pulled back toward the neutral its raw values + // actually represent, fading in over the last 1.5% of range. Smoothly, + // because a hard switch puts a visible edge around every highlight where + // the two treatments meet — a rim light on skin is the worst case, and it + // is the one people notice. + // + // The neutral chosen is the balanced grey of the same brightness, so the + // highlight keeps its luminance and loses only the cast. + if (clipped > 0.0) {{ + let neutral = vec3(max(c.r, max(c.g, c.b))); + c = mix(c, neutral, clipped); + }} +" + ) + }; + let source = format!( "// GENERATED — do not edit. // @@ -1213,51 +1317,7 @@ fn main(@builtin(global_invocation_id) gid: vec3) {{ }} {prologue} - // A non-linear source is already display-encoded; undo that so the - // operations below see linear colour whatever the source was. - let non_linear = u.as_shot_wb.w > 0.5; - if (non_linear) {{ - c = decode_srgb(c); - }} - - // As-shot white balance. Applied unconditionally, before any operation, - // because it is part of *interpreting* the sensor rather than an edit: a - // Bayer sensor's green photosites collect far more signal than its red - // and blue, so raw camera-space values are strongly green and no amount - // of later correction recovers a neutral image from them. The white - // balance operation, when active, applies its own offset on top of this. - // - // A non-linear source has already had this applied in-camera; the uniform - // is neutral there, so this is a multiply by one rather than a branch. - // How close this pixel was to saturation before any balance was applied. - // A photosite at its white level carries no colour information — every - // channel simply stopped counting — so the balance below must not be - // allowed to tint it. - let clipped = smoothstep({clip_onset}, 1.0, max(c.r, max(c.g, c.b))); - - c = c * u.as_shot_wb.rgb; - - // **Highlight desaturation, and without it every blown sky is magenta.** - // - // A fully clipped pixel arrives as (1, 1, 1). The as-shot multipliers are - // not neutral — on a Canon 6D they are (1.93, 1.00, 1.68) — so balancing - // sends it to exactly that, and the camera matrix then produces R 2.88, - // G 0.51, B 2.03. Red and blue clip at one and green does not, which is - // magenta. The balance is correct; the input was not a colour. - // - // So a saturated pixel is pulled back toward the neutral its raw values - // actually represent, fading in over the last 1.5% of range. Smoothly, - // because a hard switch puts a visible edge around every highlight where - // the two treatments meet — a rim light on skin is the worst case, and it - // is the one people notice. - // - // The neutral chosen is the balanced grey of the same brightness, so the - // highlight keeps its luminance and loses only the cast. - if (clipped > 0.0) {{ - let neutral = vec3(max(c.r, max(c.g, c.b))); - c = mix(c, neutral, clipped); - }} -{body} +{head}{body} {rendering_tail}{to_output}{reveal_block} {store} }} @@ -1294,12 +1354,25 @@ fn main(@builtin(global_invocation_id) gid: vec3) {{ output as u64, ); + // TRACES: FR-DEV-3j + // The fused pass that stops for a detail stage hands its view transform + // to a pass of its own, composed here from the same inputs so the two + // halves cannot come from different edits. + let view = (output_mode == OutputMode::LinearWorking).then(|| { + Box::new(compose_inner( + ops, framing, output, masks, spots, warps, reveal, None, smooth, true, + )) + }); + ComposedShader { source, uniforms: uniform_values, structure_hash, output_mode, - sample_key, + // The view pass reads the intermediate, not the source, so the + // sample cache has nothing to say about it. + sample_key: if view_pass { None } else { sample_key }, + view, } } @@ -2512,6 +2585,54 @@ mod tests { } } + #[test] + fn a_detail_stage_puts_the_view_transform_after_it() { + // TRACES: FR-DEV-3j | FR-DEV-2 + // D19's second finding: the fused pass stopped at "linear working + // values" for a detail stage, but after the base curve, so every + // sharpener convolved a display rendering. The fused pass must now + // stop *before* the view transform, and the view pass — which reads + // the detail stage's result — carries it, the output transform and the + // mask reveal, and nothing else. + let mut ops = crate::ops::chain(); + ops.push(Box::new(crate::detail::probe::BoxBlur::with_radius(0.05))); + let mut exposure = crate::ops::Exposure::new(); + exposure.set_param(crate::ops::exposure::EXPOSURE, 1.0); + ops.push(Box::new(exposure)); + + let fused = compose(&ops); + assert_eq!(fused.output_mode, OutputMode::LinearWorking); + assert!(!fused.source.contains("view_sigmoid")); + assert!(fused.source.contains("---- exposure ----")); + + let view = fused.view.as_deref().expect("a view pass"); + assert_eq!(view.output_mode, OutputMode::Encoded); + assert!(view.view.is_none()); + assert!(view + .source + .contains("c = textureLoad(sampled, vec2(gid.xy), 0).rgb;")); + assert!(view.source.contains("c = view_sigmoid(")); + assert!(view.source.contains("fn encode_output")); + assert_eq!( + view.source.matches("---- ").count(), + 1, + "the view pass must not run an operation the fused pass already ran" + ); + assert!(!view.source.contains("u.as_shot_wb.rgb")); + assert!(!view.source.contains("camera profile: the matrix")); + assert!(view.sample_key.is_none()); + } + + #[test] + fn an_edit_with_no_detail_stage_has_no_view_pass() { + // TRACES: FR-DEV-3j + // The common case costs what it always did: one dispatch. + let fused = compose(&crate::ops::chain()); + assert_eq!(fused.output_mode, OutputMode::Encoded); + assert!(fused.view.is_none()); + assert!(fused.source.contains("c = view_sigmoid(")); + } + #[test] fn a_detail_operation_never_contributes_a_fused_uniform() { // Slot order in the generated block is emission order, and nothing @@ -2520,9 +2641,15 @@ mod tests { // every later operation's uniforms out from under its shader. The // filter in `compose_full` prevents it; this is the assertion that the // filter is on the right side of the loop. + // + // Asserted on the field names rather than on a count: since D19 the + // edit with a detail operation also moves the view transform's + // uniforms out of this shader and into its view pass, so the two + // blocks differ in size for a reason that is not this one. let mut ops = crate::ops::chain(); ops.push(Box::new(crate::detail::probe::BoxBlur::with_radius(0.05))); - let before = compose(&crate::ops::chain()).uniforms.len(); - assert_eq!(compose(&ops).uniforms.len(), before); + let fused = compose(&ops); + assert!(!fused.source.contains("detail_probe_"), "{}", fused.source); + assert!(fused.uniforms.len() <= compose(&crate::ops::chain()).uniforms.len()); } } diff --git a/core/dr-pipeline/src/ops/capture_sharpen.rs b/core/dr-pipeline/src/ops/capture_sharpen.rs index 6739e83..93285af 100644 --- a/core/dr-pipeline/src/ops/capture_sharpen.rs +++ b/core/dr-pipeline/src/ops/capture_sharpen.rs @@ -347,8 +347,15 @@ impl Operation for CaptureSharpen { impl DetailStage for CaptureSharpen { fn passes(&self, scale: RenderScale) -> Vec { + // A radius finer than one pixel of this render: the detail it would + // act on is not in this texture — it was lost to the downscale before + // this stage ran (FR-DSP-1). Guessing at it would put sharpening on + // screen that the exported file will not contain, so there is no + // pass, and the interface is free to say `zoom to 1:1`. An empty + // chain is a whole render since D19: the fused pass's view pass + // performs the output transform whatever the chain holds. if !self.resolves(scale) { - return vec![nothing_to_sharpen()]; + return Vec::new(); } let extent = self.kernel(scale); @@ -396,41 +403,6 @@ impl DetailStage for CaptureSharpen { } } -/// The pass emitted when the radius is finer than a render pixel. -/// -/// One dispatch that changes nothing, rather than an empty chain, and the -/// difference is not stylistic. [`crate::operation::compose_full`] decides -/// from the *operations* — before any resolution is known — that an active -/// detail operation means the fused pass hands on unclipped linear values -/// instead of encoding its own output. If this returned no passes at all, -/// that decision would still stand and nothing downstream would ever perform -/// the output transform: `dr-gpu` would be handed a linear-working shader -/// with an empty chain and refuse it. -/// -/// So the honest "nothing survives at this scale" still has to carry the -/// encode, and one pass that does only that is exactly the resolve step the -/// stage would otherwise need. It costs a single copy of a proxy-sized -/// texture, which is a rounding error against the dispatches around it. -fn nothing_to_sharpen() -> DetailPass { - DetailPass { - output_scale: 1, - label: "unresolved", - // Reads only the pixel it writes, so a tile needs no halo at all. - radius: 0, - // A convolution, not a list: nothing to bind at binding 3. - storage: Vec::new(), - uniforms: Vec::new(), - wgsl: "// The chosen radius is finer than one pixel of this render, so the detail -// it would act on is not in this texture — it was lost to the downscale -// before this stage ran (FR-DSP-1). Guessing at it would put sharpening on -// screen that the exported file will not contain, so this pass passes the -// colour through unchanged and the interface is free to say `zoom to 1:1`. -// -// `c` already holds this pixel; leaving it alone is the whole body." - .to_string(), - } -} - /// One axis of the separable unsharp mask. /// /// Emitted verbatim for both passes — see [`DetailStage::passes`] for why the @@ -528,7 +500,6 @@ c = select(c, scaled, centre > 1e-5);"#; mod tests { use super::*; use crate::EditGraph; - use dr_types::ColourSpace; /// The develop chain with the sharpener turned up. /// @@ -549,7 +520,7 @@ mod tests { // The scale is what these tests vary, so it is rebuilt into the two // sizes it stands for rather than handed over: a render of the full // frame at `render_size`, from a source of `full_size`. - graph.compose_detail_for(scale.full_size(), scale.render_size(), ColourSpace::Srgb) + graph.compose_detail(scale.full_size(), scale.render_size()) } #[test] @@ -591,13 +562,11 @@ mod tests { assert_eq!(first.label, "capture_sharpen/horizontal"); assert_eq!(last.label, "capture_sharpen/vertical"); - assert!(!first.writes_output); - assert!(first.source.contains("texture_storage_2d Vec> { vec![Box::new(Dehaze::with_amount(amount))] } fn composed(amount: f32, scale: RenderScale) -> crate::ComposedDetail { - compose_detail(&ops(amount), scale, ColourSpace::Srgb) + compose_detail(&ops(amount), scale) } #[test] @@ -658,11 +657,6 @@ mod tests { let split = Split::of(Dehaze::with_amount(60.0).patch(RenderScale::full((2000, 1500)))); assert!(composed.passes.iter().all(|p| p.radius == split.extent())); - // Only the last writes the display texture, so the output transform - // happens exactly once (FR-DEV-2). - assert!(!composed.passes[0].writes_output); - assert!(composed.passes[1].writes_output); - // Nothing here uses the reduced chain — see the module documentation // for why a second operation cannot pick its own `output_scale` while // the runner holds one reduced buffer. diff --git a/core/dr-pipeline/src/ops/local_contrast.rs b/core/dr-pipeline/src/ops/local_contrast.rs index e572379..03fec92 100644 --- a/core/dr-pipeline/src/ops/local_contrast.rs +++ b/core/dr-pipeline/src/ops/local_contrast.rs @@ -878,7 +878,6 @@ c = c * exp2(stops);" mod tests { use super::*; use crate::detail::compose_detail; - use dr_types::ColourSpace; /// The two controls, as the graph would hold them. fn ops(clarity: f32, texture: f32) -> Vec> { @@ -889,7 +888,7 @@ mod tests { } fn composed(clarity: f32, texture: f32, scale: RenderScale) -> crate::ComposedDetail { - compose_detail(&ops(clarity, texture), scale, ColourSpace::Srgb) + compose_detail(&ops(clarity, texture), scale) } #[test] diff --git a/core/dr-pipeline/src/ops/noise_reduction.rs b/core/dr-pipeline/src/ops/noise_reduction.rs index d1c30e6..d1faa40 100644 --- a/core/dr-pipeline/src/ops/noise_reduction.rs +++ b/core/dr-pipeline/src/ops/noise_reduction.rs @@ -615,7 +615,6 @@ c = vec3(y0) + chroma_sum / weight_sum;"; #[cfg(test)] mod tests { use super::*; - use dr_types::ColourSpace; /// A 24 MP frame, and the panel a develop view might show it in. const FULL: (u32, u32) = (6000, 4000); @@ -629,7 +628,7 @@ mod tests { } fn compose(op: NoiseReduction, scale: RenderScale) -> crate::detail::ComposedDetail { - crate::detail::compose_detail(&chain_with(op), scale, ColourSpace::Srgb) + crate::detail::compose_detail(&chain_with(op), scale) } #[test] @@ -674,11 +673,6 @@ mod tests { // The luminance pass runs first, so the chroma guide is the denoised // luminance rather than the raw one. assert_eq!(both.passes[0].label, "noise_reduction/luminance"); - // And only the last pass in the whole chain performs the output - // transform, whichever pass that happens to be. - assert!(!both.passes[0].writes_output); - assert!(!both.passes[1].writes_output); - assert!(both.passes[2].writes_output); } #[test] diff --git a/docs/dev/traceability.md b/docs/dev/traceability.md index 15106f8..ef751d9 100644 --- a/docs/dev/traceability.md +++ b/docs/dev/traceability.md @@ -10,7 +10,7 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n | Metric | Value | |---|---| | Source files scanned | 471 | -| TRACES tags found | 1918 | +| TRACES tags found | 1925 | | Requirements defined | 193 | | Requirements deferred (post-v1) | 24 | | Requirements covered | 164 | @@ -49,14 +49,14 @@ _None._ | FR-CAT-6 | [`core/dr-catalog/src/collections.rs:1`](../../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/keywords.rs:1`](../../core/dr-catalog/src/keywords.rs#L1), [`core/dr-catalog/src/lib.rs:1`](../../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/query.rs:1`](../../core/dr-catalog/src/query.rs#L1), [`core/dr-catalog/src/rating.rs:1`](../../core/dr-catalog/src/rating.rs#L1), [`core/dr-catalog/src/rating.rs:449`](../../core/dr-catalog/src/rating.rs#L449), [`core/dr-catalog/src/rating.rs:880`](../../core/dr-catalog/src/rating.rs#L880), [`core/dr-catalog/src/schema.rs:1155`](../../core/dr-catalog/src/schema.rs#L1155), [`core/dr-types/src/place.rs:138`](../../core/dr-types/src/place.rs#L138), [`core/dr-types/src/place.rs:1`](../../core/dr-types/src/place.rs#L1), [`core/dr-types/src/selector.rs:1`](../../core/dr-types/src/selector.rs#L1), [`core/dr-types/src/settings.rs:64`](../../core/dr-types/src/settings.rs#L64), [`core/dr-types/src/time.rs:67`](../../core/dr-types/src/time.rs#L67), [`core/dr-types/src/time.rs:90`](../../core/dr-types/src/time.rs#L90), [`ui/dr-ui/src/library/filters.rs:156`](../../ui/dr-ui/src/library/filters.rs#L156), [`ui/dr-ui/src/library/filters.rs:357`](../../ui/dr-ui/src/library/filters.rs#L357), [`ui/dr-ui/src/library/filters.rs:442`](../../ui/dr-ui/src/library/filters.rs#L442), [`ui/dr-ui/src/library/filters.rs:64`](../../ui/dr-ui/src/library/filters.rs#L64), [`ui/dr-ui/src/library/spans.rs:262`](../../ui/dr-ui/src/library/spans.rs#L262), [`ui/dr-ui/src/library_ui/controller.rs:412`](../../ui/dr-ui/src/library_ui/controller.rs#L412), [`ui/dr-ui/src/library_ui/controller.rs:524`](../../ui/dr-ui/src/library_ui/controller.rs#L524), [`ui/dr-ui/src/library_ui/filter_bar.rs:256`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L256), [`ui/dr-ui/src/library_ui/filter_bar.rs:351`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L351), [`ui/dr-ui/src/library_ui/filter_bar.rs:406`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L406), [`ui/dr-ui/src/library_ui/filter_bar.rs:840`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L840), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:85`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L85), [`ui/dr-ui/ui/app.slint:656`](../../ui/dr-ui/ui/app.slint#L656), [`ui/dr-ui/ui/library.slint:113`](../../ui/dr-ui/ui/library.slint#L113), [`ui/dr-ui/ui/library.slint:1936`](../../ui/dr-ui/ui/library.slint#L1936), [`ui/dr-ui/ui/library.slint:1973`](../../ui/dr-ui/ui/library.slint#L1973), [`ui/dr-ui/ui/library.slint:2703`](../../ui/dr-ui/ui/library.slint#L2703), [`ui/dr-ui/ui/library.slint:3229`](../../ui/dr-ui/ui/library.slint#L3229), [`ui/dr-ui/ui/library.slint:488`](../../ui/dr-ui/ui/library.slint#L488), [`ui/dr-ui/ui/library.slint:5060`](../../ui/dr-ui/ui/library.slint#L5060), [`ui/dr-ui/ui/library.slint:621`](../../ui/dr-ui/ui/library.slint#L621), [`ui/dr-ui/ui/library.slint:679`](../../ui/dr-ui/ui/library.slint#L679), [`ui/dr-ui/ui/library.slint:701`](../../ui/dr-ui/ui/library.slint#L701), [`ui/dr-ui/ui/settings.slint:202`](../../ui/dr-ui/ui/settings.slint#L202), [`ui/dr-ui/ui/widgets.slint:271`](../../ui/dr-ui/ui/widgets.slint#L271) | | FR-CAT-7 | [`core/dr-catalog/src/albums.rs:1`](../../core/dr-catalog/src/albums.rs#L1), [`core/dr-catalog/src/collections.rs:1`](../../core/dr-catalog/src/collections.rs#L1), [`core/dr-catalog/src/dedup_people.rs:1`](../../core/dr-catalog/src/dedup_people.rs#L1), [`core/dr-catalog/src/merge.rs:1`](../../core/dr-catalog/src/merge.rs#L1), [`core/dr-catalog/src/sync.rs:1`](../../core/dr-catalog/src/sync.rs#L1), [`core/dr-types/src/selector.rs:1`](../../core/dr-types/src/selector.rs#L1), [`ui/dr-ui/src/collections_ui/controller.rs:263`](../../ui/dr-ui/src/collections_ui/controller.rs#L263), [`ui/dr-ui/src/collections_ui/controller.rs:273`](../../ui/dr-ui/src/collections_ui/controller.rs#L273), [`ui/dr-ui/src/collections_ui/controller.rs:296`](../../ui/dr-ui/src/collections_ui/controller.rs#L296), [`ui/dr-ui/src/collections_ui/controller.rs:317`](../../ui/dr-ui/src/collections_ui/controller.rs#L317), [`ui/dr-ui/src/collections_ui/controller.rs:46`](../../ui/dr-ui/src/collections_ui/controller.rs#L46), [`ui/dr-ui/src/collections_ui/drag.rs:274`](../../ui/dr-ui/src/collections_ui/drag.rs#L274), [`ui/dr-ui/src/collections_ui/mod.rs:1`](../../ui/dr-ui/src/collections_ui/mod.rs#L1), [`ui/dr-ui/src/collections_ui/press.rs:258`](../../ui/dr-ui/src/collections_ui/press.rs#L258), [`ui/dr-ui/src/collections_ui/press.rs:490`](../../ui/dr-ui/src/collections_ui/press.rs#L490), [`ui/dr-ui/src/collections_ui/press.rs:54`](../../ui/dr-ui/src/collections_ui/press.rs#L54), [`ui/dr-ui/src/collections_ui/rename_menu.rs:196`](../../ui/dr-ui/src/collections_ui/rename_menu.rs#L196), [`ui/dr-ui/src/collections_ui/rename_menu.rs:21`](../../ui/dr-ui/src/collections_ui/rename_menu.rs#L21), [`ui/dr-ui/src/collections_ui/tree_sync.rs:251`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L251), [`ui/dr-ui/src/collections_ui/tree_sync.rs:322`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L322), [`ui/dr-ui/src/collections_ui/tree_sync.rs:344`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L344), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:121`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L121), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:171`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L171), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:444`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L444), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:522`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L522), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:586`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L586), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:344`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L344), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:394`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L394), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:517`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L517), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:581`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L581), [`ui/dr-ui/src/derived_sync.rs:1`](../../ui/dr-ui/src/derived_sync.rs#L1), [`ui/dr-ui/src/library/spans.rs:131`](../../ui/dr-ui/src/library/spans.rs#L131), [`ui/dr-ui/src/library/spans.rs:50`](../../ui/dr-ui/src/library/spans.rs#L50), [`ui/dr-ui/src/library/spans.rs:76`](../../ui/dr-ui/src/library/spans.rs#L76), [`ui/dr-ui/src/library_ui/sync.rs:236`](../../ui/dr-ui/src/library_ui/sync.rs#L236), [`ui/dr-ui/src/library_ui/timeline.rs:513`](../../ui/dr-ui/src/library_ui/timeline.rs#L513), [`ui/dr-ui/src/library_ui/window.rs:359`](../../ui/dr-ui/src/library_ui/window.rs#L359), [`ui/dr-ui/src/library_ui/window.rs:395`](../../ui/dr-ui/src/library_ui/window.rs#L395), [`ui/dr-ui/ui/app.slint:3521`](../../ui/dr-ui/ui/app.slint#L3521), [`ui/dr-ui/ui/collections.slint:1283`](../../ui/dr-ui/ui/collections.slint#L1283), [`ui/dr-ui/ui/collections.slint:4`](../../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:616`](../../ui/dr-ui/ui/collections.slint#L616), [`ui/dr-ui/ui/library.slint:1367`](../../ui/dr-ui/ui/library.slint#L1367), [`ui/dr-ui/ui/library.slint:1734`](../../ui/dr-ui/ui/library.slint#L1734), [`ui/dr-ui/ui/library.slint:3685`](../../ui/dr-ui/ui/library.slint#L3685), [`ui/dr-ui/ui/library.slint:488`](../../ui/dr-ui/ui/library.slint#L488), [`ui/dr-ui/ui/library.slint:5038`](../../ui/dr-ui/ui/library.slint#L5038), [`ui/dr-ui/ui/library.slint:5180`](../../ui/dr-ui/ui/library.slint#L5180), [`ui/dr-ui/ui/library.slint:518`](../../ui/dr-ui/ui/library.slint#L518), [`ui/dr-ui/ui/library.slint:567`](../../ui/dr-ui/ui/library.slint#L567), [`ui/dr-ui/ui/library.slint:577`](../../ui/dr-ui/ui/library.slint#L577) | | FR-CAT-8 | [`core/dr-catalog/src/schema.rs:770`](../../core/dr-catalog/src/schema.rs#L770), [`core/dr-pipeline/src/coverage.rs:1`](../../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/graph.rs:587`](../../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:642`](../../core/dr-pipeline/src/graph.rs#L642), [`core/dr-pipeline/src/ops/curve.rs:137`](../../core/dr-pipeline/src/ops/curve.rs#L137), [`core/dr-pipeline/src/ops/curve.rs:656`](../../core/dr-pipeline/src/ops/curve.rs#L656), [`core/dr-pipeline/src/sidecar.rs:1433`](../../core/dr-pipeline/src/sidecar.rs#L1433), [`core/dr-pipeline/src/sidecar.rs:2275`](../../core/dr-pipeline/src/sidecar.rs#L2275), [`core/dr-pipeline/src/sidecar.rs:99`](../../core/dr-pipeline/src/sidecar.rs#L99), [`core/dr-pipeline/src/state.rs:1`](../../core/dr-pipeline/src/state.rs#L1), [`core/dr-pipeline/src/state.rs:75`](../../core/dr-pipeline/src/state.rs#L75), [`core/dr-pipeline/tests/tone_curve.rs:34`](../../core/dr-pipeline/tests/tone_curve.rs#L34), [`core/dr-sync/src/scan.rs:31`](../../core/dr-sync/src/scan.rs#L31), [`core/dr-sync/src/scan.rs:56`](../../core/dr-sync/src/scan.rs#L56), [`core/dr-sync/src/scan.rs:926`](../../core/dr-sync/src/scan.rs#L926), [`ui/dr-ui/src/develop/mask_ops.rs:1076`](../../ui/dr-ui/src/develop/mask_ops.rs#L1076), [`ui/dr-ui/src/develop/mask_ops.rs:1130`](../../ui/dr-ui/src/develop/mask_ops.rs#L1130), [`ui/dr-ui/src/develop/mask_ops.rs:178`](../../ui/dr-ui/src/develop/mask_ops.rs#L178), [`ui/dr-ui/src/develop/masks.rs:743`](../../ui/dr-ui/src/develop/masks.rs#L743), [`ui/dr-ui/src/develop/session.rs:566`](../../ui/dr-ui/src/develop/session.rs#L566), [`ui/dr-ui/src/develop/session.rs:600`](../../ui/dr-ui/src/develop/session.rs#L600), [`ui/dr-ui/src/export.rs:925`](../../ui/dr-ui/src/export.rs#L925), [`ui/dr-ui/src/lib.rs:1202`](../../ui/dr-ui/src/lib.rs#L1202), [`ui/dr-ui/src/lib.rs:1262`](../../ui/dr-ui/src/lib.rs#L1262), [`ui/dr-ui/src/lib.rs:2660`](../../ui/dr-ui/src/lib.rs#L2660), [`ui/dr-ui/src/lib.rs:2853`](../../ui/dr-ui/src/lib.rs#L2853), [`ui/dr-ui/src/lib.rs:809`](../../ui/dr-ui/src/lib.rs#L809), [`ui/dr-ui/src/library/scan.rs:227`](../../ui/dr-ui/src/library/scan.rs#L227), [`ui/dr-ui/src/library/scan.rs:262`](../../ui/dr-ui/src/library/scan.rs#L262), [`ui/dr-ui/src/library/scan.rs:35`](../../ui/dr-ui/src/library/scan.rs#L35), [`ui/dr-ui/src/library/sidecar.rs:103`](../../ui/dr-ui/src/library/sidecar.rs#L103), [`ui/dr-ui/src/library/sidecar.rs:12`](../../ui/dr-ui/src/library/sidecar.rs#L12), [`ui/dr-ui/src/library/sidecar.rs:381`](../../ui/dr-ui/src/library/sidecar.rs#L381), [`ui/dr-ui/src/library/sidecar.rs:66`](../../ui/dr-ui/src/library/sidecar.rs#L66), [`ui/dr-ui/src/library/thumbnails_fetch.rs:414`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L414), [`ui/dr-ui/src/library_ui/grid.rs:789`](../../ui/dr-ui/src/library_ui/grid.rs#L789), [`ui/dr-ui/src/library_ui/open.rs:456`](../../ui/dr-ui/src/library_ui/open.rs#L456), [`ui/dr-ui/src/sidecar_cache.rs:1`](../../ui/dr-ui/src/sidecar_cache.rs#L1) | -| FR-CAT-9 | [`core/dr-catalog/src/cache.rs:1`](../../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/schema.rs:1212`](../../core/dr-catalog/src/schema.rs#L1212), [`core/dr-catalog/src/walk.rs:1000`](../../core/dr-catalog/src/walk.rs#L1000), [`core/dr-catalog/src/walk.rs:161`](../../core/dr-catalog/src/walk.rs#L161), [`core/dr-catalog/src/walk.rs:1`](../../core/dr-catalog/src/walk.rs#L1), [`core/dr-catalog/src/walk.rs:432`](../../core/dr-catalog/src/walk.rs#L432), [`core/dr-catalog/src/walk.rs:695`](../../core/dr-catalog/src/walk.rs#L695), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`core/dr-sync/src/error.rs:113`](../../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/reachability.rs:1`](../../core/dr-sync/src/reachability.rs#L1), [`core/dr-sync/src/scan.rs:211`](../../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../../core/dr-sync/src/scan.rs#L519), [`core/dr-types/src/lib.rs:122`](../../core/dr-types/src/lib.rs#L122), [`ui/dr-ui/src/develop/render.rs:626`](../../ui/dr-ui/src/develop/render.rs#L626), [`ui/dr-ui/src/develop/render.rs:669`](../../ui/dr-ui/src/develop/render.rs#L669), [`ui/dr-ui/src/library/filters.rs:89`](../../ui/dr-ui/src/library/filters.rs#L89), [`ui/dr-ui/src/library/scan.rs:127`](../../ui/dr-ui/src/library/scan.rs#L127), [`ui/dr-ui/src/library/scan.rs:180`](../../ui/dr-ui/src/library/scan.rs#L180), [`ui/dr-ui/src/library/scan.rs:211`](../../ui/dr-ui/src/library/scan.rs#L211), [`ui/dr-ui/src/library/scan.rs:262`](../../ui/dr-ui/src/library/scan.rs#L262), [`ui/dr-ui/src/library/scan.rs:636`](../../ui/dr-ui/src/library/scan.rs#L636), [`ui/dr-ui/src/library/sidecar.rs:103`](../../ui/dr-ui/src/library/sidecar.rs#L103), [`ui/dr-ui/src/library/sidecar.rs:365`](../../ui/dr-ui/src/library/sidecar.rs#L365), [`ui/dr-ui/src/library/sidecar.rs:381`](../../ui/dr-ui/src/library/sidecar.rs#L381), [`ui/dr-ui/src/library/sidecar.rs:435`](../../ui/dr-ui/src/library/sidecar.rs#L435), [`ui/dr-ui/src/library/spans.rs:378`](../../ui/dr-ui/src/library/spans.rs#L378), [`ui/dr-ui/src/library/thumbnails_fetch.rs:394`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L394), [`ui/dr-ui/src/library/thumbnails_fetch.rs:450`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L450), [`ui/dr-ui/src/library/thumbnails_gen.rs:75`](../../ui/dr-ui/src/library/thumbnails_gen.rs#L75), [`ui/dr-ui/src/library_ui/controller.rs:300`](../../ui/dr-ui/src/library_ui/controller.rs#L300), [`ui/dr-ui/src/library_ui/controller.rs:336`](../../ui/dr-ui/src/library_ui/controller.rs#L336), [`ui/dr-ui/src/library_ui/controller.rs:344`](../../ui/dr-ui/src/library_ui/controller.rs#L344), [`ui/dr-ui/src/library_ui/controller.rs:592`](../../ui/dr-ui/src/library_ui/controller.rs#L592), [`ui/dr-ui/src/library_ui/controller.rs:709`](../../ui/dr-ui/src/library_ui/controller.rs#L709), [`ui/dr-ui/src/library_ui/filter_bar.rs:461`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L461), [`ui/dr-ui/src/library_ui/filter_bar.rs:547`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L547), [`ui/dr-ui/src/library_ui/offline.rs:561`](../../ui/dr-ui/src/library_ui/offline.rs#L561), [`ui/dr-ui/src/library_ui/offline.rs:607`](../../ui/dr-ui/src/library_ui/offline.rs#L607), [`ui/dr-ui/src/library_ui/offline.rs:623`](../../ui/dr-ui/src/library_ui/offline.rs#L623), [`ui/dr-ui/src/library_ui/open.rs:536`](../../ui/dr-ui/src/library_ui/open.rs#L536), [`ui/dr-ui/src/library_ui/open.rs:616`](../../ui/dr-ui/src/library_ui/open.rs#L616), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:75`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L75), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:890`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L890), [`ui/dr-ui/src/library_ui/sync.rs:288`](../../ui/dr-ui/src/library_ui/sync.rs#L288), [`ui/dr-ui/src/library_ui/sync.rs:422`](../../ui/dr-ui/src/library_ui/sync.rs#L422), [`ui/dr-ui/src/library_ui/sync.rs:84`](../../ui/dr-ui/src/library_ui/sync.rs#L84), [`ui/dr-ui/src/library_ui/window.rs:678`](../../ui/dr-ui/src/library_ui/window.rs#L678), [`ui/dr-ui/src/library_ui/window.rs:958`](../../ui/dr-ui/src/library_ui/window.rs#L958), [`ui/dr-ui/src/presets.rs:486`](../../ui/dr-ui/src/presets.rs#L486), [`ui/dr-ui/src/presets.rs:498`](../../ui/dr-ui/src/presets.rs#L498), [`ui/dr-ui/src/sidecar_cache.rs:1`](../../ui/dr-ui/src/sidecar_cache.rs#L1), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | +| FR-CAT-9 | [`core/dr-catalog/src/cache.rs:1`](../../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/schema.rs:1212`](../../core/dr-catalog/src/schema.rs#L1212), [`core/dr-catalog/src/walk.rs:1000`](../../core/dr-catalog/src/walk.rs#L1000), [`core/dr-catalog/src/walk.rs:161`](../../core/dr-catalog/src/walk.rs#L161), [`core/dr-catalog/src/walk.rs:1`](../../core/dr-catalog/src/walk.rs#L1), [`core/dr-catalog/src/walk.rs:432`](../../core/dr-catalog/src/walk.rs#L432), [`core/dr-catalog/src/walk.rs:695`](../../core/dr-catalog/src/walk.rs#L695), [`core/dr-sync-nextcloud/src/desktop_client.rs:35`](../../core/dr-sync-nextcloud/src/desktop_client.rs#L35), [`core/dr-sync/src/error.rs:113`](../../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/reachability.rs:1`](../../core/dr-sync/src/reachability.rs#L1), [`core/dr-sync/src/scan.rs:211`](../../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../../core/dr-sync/src/scan.rs#L519), [`core/dr-types/src/lib.rs:122`](../../core/dr-types/src/lib.rs#L122), [`ui/dr-ui/src/develop/render.rs:617`](../../ui/dr-ui/src/develop/render.rs#L617), [`ui/dr-ui/src/develop/render.rs:660`](../../ui/dr-ui/src/develop/render.rs#L660), [`ui/dr-ui/src/library/filters.rs:89`](../../ui/dr-ui/src/library/filters.rs#L89), [`ui/dr-ui/src/library/scan.rs:127`](../../ui/dr-ui/src/library/scan.rs#L127), [`ui/dr-ui/src/library/scan.rs:180`](../../ui/dr-ui/src/library/scan.rs#L180), [`ui/dr-ui/src/library/scan.rs:211`](../../ui/dr-ui/src/library/scan.rs#L211), [`ui/dr-ui/src/library/scan.rs:262`](../../ui/dr-ui/src/library/scan.rs#L262), [`ui/dr-ui/src/library/scan.rs:636`](../../ui/dr-ui/src/library/scan.rs#L636), [`ui/dr-ui/src/library/sidecar.rs:103`](../../ui/dr-ui/src/library/sidecar.rs#L103), [`ui/dr-ui/src/library/sidecar.rs:365`](../../ui/dr-ui/src/library/sidecar.rs#L365), [`ui/dr-ui/src/library/sidecar.rs:381`](../../ui/dr-ui/src/library/sidecar.rs#L381), [`ui/dr-ui/src/library/sidecar.rs:435`](../../ui/dr-ui/src/library/sidecar.rs#L435), [`ui/dr-ui/src/library/spans.rs:378`](../../ui/dr-ui/src/library/spans.rs#L378), [`ui/dr-ui/src/library/thumbnails_fetch.rs:394`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L394), [`ui/dr-ui/src/library/thumbnails_fetch.rs:450`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L450), [`ui/dr-ui/src/library/thumbnails_gen.rs:75`](../../ui/dr-ui/src/library/thumbnails_gen.rs#L75), [`ui/dr-ui/src/library_ui/controller.rs:300`](../../ui/dr-ui/src/library_ui/controller.rs#L300), [`ui/dr-ui/src/library_ui/controller.rs:336`](../../ui/dr-ui/src/library_ui/controller.rs#L336), [`ui/dr-ui/src/library_ui/controller.rs:344`](../../ui/dr-ui/src/library_ui/controller.rs#L344), [`ui/dr-ui/src/library_ui/controller.rs:592`](../../ui/dr-ui/src/library_ui/controller.rs#L592), [`ui/dr-ui/src/library_ui/controller.rs:709`](../../ui/dr-ui/src/library_ui/controller.rs#L709), [`ui/dr-ui/src/library_ui/filter_bar.rs:461`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L461), [`ui/dr-ui/src/library_ui/filter_bar.rs:547`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L547), [`ui/dr-ui/src/library_ui/offline.rs:561`](../../ui/dr-ui/src/library_ui/offline.rs#L561), [`ui/dr-ui/src/library_ui/offline.rs:607`](../../ui/dr-ui/src/library_ui/offline.rs#L607), [`ui/dr-ui/src/library_ui/offline.rs:623`](../../ui/dr-ui/src/library_ui/offline.rs#L623), [`ui/dr-ui/src/library_ui/open.rs:536`](../../ui/dr-ui/src/library_ui/open.rs#L536), [`ui/dr-ui/src/library_ui/open.rs:616`](../../ui/dr-ui/src/library_ui/open.rs#L616), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:75`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L75), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:890`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L890), [`ui/dr-ui/src/library_ui/sync.rs:288`](../../ui/dr-ui/src/library_ui/sync.rs#L288), [`ui/dr-ui/src/library_ui/sync.rs:422`](../../ui/dr-ui/src/library_ui/sync.rs#L422), [`ui/dr-ui/src/library_ui/sync.rs:84`](../../ui/dr-ui/src/library_ui/sync.rs#L84), [`ui/dr-ui/src/library_ui/window.rs:678`](../../ui/dr-ui/src/library_ui/window.rs#L678), [`ui/dr-ui/src/library_ui/window.rs:958`](../../ui/dr-ui/src/library_ui/window.rs#L958), [`ui/dr-ui/src/presets.rs:486`](../../ui/dr-ui/src/presets.rs#L486), [`ui/dr-ui/src/presets.rs:498`](../../ui/dr-ui/src/presets.rs#L498), [`ui/dr-ui/src/sidecar_cache.rs:1`](../../ui/dr-ui/src/sidecar_cache.rs#L1), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | | FR-CULL-1 | [`core/dr-decode/src/preview.rs:121`](../../core/dr-decode/src/preview.rs#L121) | | FR-CULL-10 | [`core/dr-catalog/src/dedup_people.rs:1`](../../core/dr-catalog/src/dedup_people.rs#L1), [`core/dr-catalog/src/faces.rs:1662`](../../core/dr-catalog/src/faces.rs#L1662), [`core/dr-catalog/src/faces.rs:1680`](../../core/dr-catalog/src/faces.rs#L1680), [`core/dr-catalog/src/faces.rs:1`](../../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:1041`](../../core/dr-catalog/src/schema.rs#L1041), [`core/dr-catalog/src/schema.rs:633`](../../core/dr-catalog/src/schema.rs#L633), [`core/dr-catalog/src/schema.rs:811`](../../core/dr-catalog/src/schema.rs#L811), [`core/dr-face/src/assign.rs:1`](../../core/dr-face/src/assign.rs#L1), [`core/dr-face/src/neighbours.rs:1`](../../core/dr-face/src/neighbours.rs#L1), [`core/dr-face/src/references.rs:1`](../../core/dr-face/src/references.rs#L1), [`core/dr-types/src/settings.rs:129`](../../core/dr-types/src/settings.rs#L129), [`ui/dr-ui/src/develop/segmentation.rs:104`](../../ui/dr-ui/src/develop/segmentation.rs#L104), [`ui/dr-ui/src/develop/segmentation.rs:170`](../../ui/dr-ui/src/develop/segmentation.rs#L170), [`ui/dr-ui/src/develop/segmentation.rs:590`](../../ui/dr-ui/src/develop/segmentation.rs#L590), [`ui/dr-ui/src/develop/segmentation.rs:95`](../../ui/dr-ui/src/develop/segmentation.rs#L95), [`ui/dr-ui/src/develop/session.rs:23`](../../ui/dr-ui/src/develop/session.rs#L23), [`ui/dr-ui/src/faces.rs:1`](../../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/identity.rs:1`](../../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/src/identity_ui.rs:1472`](../../ui/dr-ui/src/identity_ui.rs#L1472), [`ui/dr-ui/src/identity_ui.rs:1`](../../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/lib.rs:2825`](../../ui/dr-ui/src/lib.rs#L2825), [`ui/dr-ui/src/repairs.rs:1`](../../ui/dr-ui/src/repairs.rs#L1), [`ui/dr-ui/ui/identity.slint:1`](../../ui/dr-ui/ui/identity.slint#L1), [`ui/dr-ui/ui/settings.slint:469`](../../ui/dr-ui/ui/settings.slint#L469), [`ui/dr-ui/ui/settings.slint:95`](../../ui/dr-ui/ui/settings.slint#L95) | | FR-CULL-11 | [`core/dr-catalog/src/faces.rs:1`](../../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:1041`](../../core/dr-catalog/src/schema.rs#L1041), [`ui/dr-ui/src/identity.rs:1`](../../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/src/identity_ui.rs:1`](../../ui/dr-ui/src/identity_ui.rs#L1), [`ui/dr-ui/src/library/filters.rs:110`](../../ui/dr-ui/src/library/filters.rs#L110), [`ui/dr-ui/src/library/filters.rs:164`](../../ui/dr-ui/src/library/filters.rs#L164), [`ui/dr-ui/ui/identity.slint:1`](../../ui/dr-ui/ui/identity.slint#L1) | | FR-CULL-12 | [`core/dr-catalog/src/dedup_people.rs:1`](../../core/dr-catalog/src/dedup_people.rs#L1), [`core/dr-catalog/src/faces.rs:1`](../../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:1041`](../../core/dr-catalog/src/schema.rs#L1041), [`core/dr-catalog/src/schema.rs:633`](../../core/dr-catalog/src/schema.rs#L633), [`ui/dr-ui/src/identity.rs:1`](../../ui/dr-ui/src/identity.rs#L1), [`ui/dr-ui/ui/identity.slint:1`](../../ui/dr-ui/ui/identity.slint#L1) | | FR-CULL-13 | [`core/dr-catalog/src/schema.rs:947`](../../core/dr-catalog/src/schema.rs#L947), [`core/dr-types/src/place.rs:133`](../../core/dr-types/src/place.rs#L133), [`tools/traceability/src/verdicts.rs:1`](../../tools/traceability/src/verdicts.rs#L1), [`ui/dr-ui/src/identity.rs:104`](../../ui/dr-ui/src/identity.rs#L104), [`ui/dr-ui/src/library/filters.rs:136`](../../ui/dr-ui/src/library/filters.rs#L136), [`ui/dr-ui/src/library/filters.rs:763`](../../ui/dr-ui/src/library/filters.rs#L763), [`ui/dr-ui/src/library/filters.rs:806`](../../ui/dr-ui/src/library/filters.rs#L806), [`ui/dr-ui/src/library/filters.rs:844`](../../ui/dr-ui/src/library/filters.rs#L844), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1085`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1085), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:379`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L379), [`ui/dr-ui/ui/identity.slint:64`](../../ui/dr-ui/ui/identity.slint#L64), [`ui/dr-ui/ui/library.slint:1928`](../../ui/dr-ui/ui/library.slint#L1928), [`ui/dr-ui/ui/library.slint:735`](../../ui/dr-ui/ui/library.slint#L735) | | FR-CULL-2 | [`core/dr-decode/src/locate.rs:1`](../../core/dr-decode/src/locate.rs#L1), [`core/dr-decode/src/preview.rs:148`](../../core/dr-decode/src/preview.rs#L148), [`ui/dr-ui/src/decoder_seam.rs:214`](../../ui/dr-ui/src/decoder_seam.rs#L214), [`ui/dr-ui/src/import.rs:473`](../../ui/dr-ui/src/import.rs#L473) | -| FR-CULL-3 | [`core/dr-gpu/src/focus.rs:154`](../../core/dr-gpu/src/focus.rs#L154), [`core/dr-gpu/src/focus.rs:186`](../../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/raw_histogram.rs:129`](../../core/dr-gpu/src/raw_histogram.rs#L129), [`core/dr-gpu/src/raw_histogram.rs:1`](../../core/dr-gpu/src/raw_histogram.rs#L1), [`core/dr-gpu/src/raw_histogram.rs:272`](../../core/dr-gpu/src/raw_histogram.rs#L272), [`core/dr-gpu/src/raw_histogram.rs:407`](../../core/dr-gpu/src/raw_histogram.rs#L407), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`core/dr-gpu/src/shaders/raw_histogram.wgsl:1`](../../core/dr-gpu/src/shaders/raw_histogram.wgsl#L1), [`ui/dr-ui/src/develop/render.rs:1491`](../../ui/dr-ui/src/develop/render.rs#L1491), [`ui/dr-ui/src/develop/render.rs:1555`](../../ui/dr-ui/src/develop/render.rs#L1555), [`ui/dr-ui/src/develop/render.rs:1578`](../../ui/dr-ui/src/develop/render.rs#L1578), [`ui/dr-ui/src/develop/render.rs:317`](../../ui/dr-ui/src/develop/render.rs#L317), [`ui/dr-ui/src/develop/render.rs:330`](../../ui/dr-ui/src/develop/render.rs#L330), [`ui/dr-ui/src/develop/render.rs:375`](../../ui/dr-ui/src/develop/render.rs#L375), [`ui/dr-ui/src/develop/render.rs:386`](../../ui/dr-ui/src/develop/render.rs#L386), [`ui/dr-ui/src/develop/render.rs:392`](../../ui/dr-ui/src/develop/render.rs#L392), [`ui/dr-ui/src/develop/render.rs:409`](../../ui/dr-ui/src/develop/render.rs#L409), [`ui/dr-ui/src/develop/session.rs:122`](../../ui/dr-ui/src/develop/session.rs#L122), [`ui/dr-ui/src/develop/session.rs:142`](../../ui/dr-ui/src/develop/session.rs#L142), [`ui/dr-ui/src/develop/session.rs:148`](../../ui/dr-ui/src/develop/session.rs#L148), [`ui/dr-ui/src/develop_ui.rs:1419`](../../ui/dr-ui/src/develop_ui.rs#L1419), [`ui/dr-ui/src/histogram.rs:1`](../../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/histogram.rs:208`](../../ui/dr-ui/src/histogram.rs#L208), [`ui/dr-ui/src/histogram.rs:228`](../../ui/dr-ui/src/histogram.rs#L228), [`ui/dr-ui/src/histogram.rs:272`](../../ui/dr-ui/src/histogram.rs#L272), [`ui/dr-ui/src/histogram.rs:544`](../../ui/dr-ui/src/histogram.rs#L544), [`ui/dr-ui/src/histogram.rs:565`](../../ui/dr-ui/src/histogram.rs#L565), [`ui/dr-ui/src/histogram.rs:593`](../../ui/dr-ui/src/histogram.rs#L593), [`ui/dr-ui/src/histogram.rs:621`](../../ui/dr-ui/src/histogram.rs#L621), [`ui/dr-ui/src/histogram.rs:658`](../../ui/dr-ui/src/histogram.rs#L658), [`ui/dr-ui/src/lib.rs:1291`](../../ui/dr-ui/src/lib.rs#L1291), [`ui/dr-ui/src/lib.rs:2174`](../../ui/dr-ui/src/lib.rs#L2174), [`ui/dr-ui/src/lib.rs:2304`](../../ui/dr-ui/src/lib.rs#L2304), [`ui/dr-ui/src/lib.rs:2347`](../../ui/dr-ui/src/lib.rs#L2347), [`ui/dr-ui/src/lib.rs:480`](../../ui/dr-ui/src/lib.rs#L480), [`ui/dr-ui/src/peaking.rs:1`](../../ui/dr-ui/src/peaking.rs#L1), [`ui/dr-ui/ui/app.slint:182`](../../ui/dr-ui/ui/app.slint#L182), [`ui/dr-ui/ui/app.slint:1917`](../../ui/dr-ui/ui/app.slint#L1917), [`ui/dr-ui/ui/app.slint:3294`](../../ui/dr-ui/ui/app.slint#L3294), [`ui/dr-ui/ui/peaking.slint:1`](../../ui/dr-ui/ui/peaking.slint#L1), [`ui/dr-ui/ui/peaking.slint:25`](../../ui/dr-ui/ui/peaking.slint#L25), [`ui/dr-ui/ui/peaking.slint:56`](../../ui/dr-ui/ui/peaking.slint#L56), [`ui/dr-ui/ui/peaking.slint:91`](../../ui/dr-ui/ui/peaking.slint#L91) | +| FR-CULL-3 | [`core/dr-gpu/src/focus.rs:154`](../../core/dr-gpu/src/focus.rs#L154), [`core/dr-gpu/src/focus.rs:186`](../../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/raw_histogram.rs:129`](../../core/dr-gpu/src/raw_histogram.rs#L129), [`core/dr-gpu/src/raw_histogram.rs:1`](../../core/dr-gpu/src/raw_histogram.rs#L1), [`core/dr-gpu/src/raw_histogram.rs:272`](../../core/dr-gpu/src/raw_histogram.rs#L272), [`core/dr-gpu/src/raw_histogram.rs:407`](../../core/dr-gpu/src/raw_histogram.rs#L407), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`core/dr-gpu/src/shaders/raw_histogram.wgsl:1`](../../core/dr-gpu/src/shaders/raw_histogram.wgsl#L1), [`ui/dr-ui/src/develop/render.rs:1482`](../../ui/dr-ui/src/develop/render.rs#L1482), [`ui/dr-ui/src/develop/render.rs:1546`](../../ui/dr-ui/src/develop/render.rs#L1546), [`ui/dr-ui/src/develop/render.rs:1569`](../../ui/dr-ui/src/develop/render.rs#L1569), [`ui/dr-ui/src/develop/render.rs:308`](../../ui/dr-ui/src/develop/render.rs#L308), [`ui/dr-ui/src/develop/render.rs:321`](../../ui/dr-ui/src/develop/render.rs#L321), [`ui/dr-ui/src/develop/render.rs:366`](../../ui/dr-ui/src/develop/render.rs#L366), [`ui/dr-ui/src/develop/render.rs:377`](../../ui/dr-ui/src/develop/render.rs#L377), [`ui/dr-ui/src/develop/render.rs:383`](../../ui/dr-ui/src/develop/render.rs#L383), [`ui/dr-ui/src/develop/render.rs:400`](../../ui/dr-ui/src/develop/render.rs#L400), [`ui/dr-ui/src/develop/session.rs:122`](../../ui/dr-ui/src/develop/session.rs#L122), [`ui/dr-ui/src/develop/session.rs:142`](../../ui/dr-ui/src/develop/session.rs#L142), [`ui/dr-ui/src/develop/session.rs:148`](../../ui/dr-ui/src/develop/session.rs#L148), [`ui/dr-ui/src/develop_ui.rs:1419`](../../ui/dr-ui/src/develop_ui.rs#L1419), [`ui/dr-ui/src/histogram.rs:1`](../../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/histogram.rs:208`](../../ui/dr-ui/src/histogram.rs#L208), [`ui/dr-ui/src/histogram.rs:228`](../../ui/dr-ui/src/histogram.rs#L228), [`ui/dr-ui/src/histogram.rs:272`](../../ui/dr-ui/src/histogram.rs#L272), [`ui/dr-ui/src/histogram.rs:544`](../../ui/dr-ui/src/histogram.rs#L544), [`ui/dr-ui/src/histogram.rs:565`](../../ui/dr-ui/src/histogram.rs#L565), [`ui/dr-ui/src/histogram.rs:593`](../../ui/dr-ui/src/histogram.rs#L593), [`ui/dr-ui/src/histogram.rs:621`](../../ui/dr-ui/src/histogram.rs#L621), [`ui/dr-ui/src/histogram.rs:658`](../../ui/dr-ui/src/histogram.rs#L658), [`ui/dr-ui/src/lib.rs:1291`](../../ui/dr-ui/src/lib.rs#L1291), [`ui/dr-ui/src/lib.rs:2174`](../../ui/dr-ui/src/lib.rs#L2174), [`ui/dr-ui/src/lib.rs:2304`](../../ui/dr-ui/src/lib.rs#L2304), [`ui/dr-ui/src/lib.rs:2347`](../../ui/dr-ui/src/lib.rs#L2347), [`ui/dr-ui/src/lib.rs:480`](../../ui/dr-ui/src/lib.rs#L480), [`ui/dr-ui/src/peaking.rs:1`](../../ui/dr-ui/src/peaking.rs#L1), [`ui/dr-ui/ui/app.slint:182`](../../ui/dr-ui/ui/app.slint#L182), [`ui/dr-ui/ui/app.slint:1917`](../../ui/dr-ui/ui/app.slint#L1917), [`ui/dr-ui/ui/app.slint:3294`](../../ui/dr-ui/ui/app.slint#L3294), [`ui/dr-ui/ui/peaking.slint:1`](../../ui/dr-ui/ui/peaking.slint#L1), [`ui/dr-ui/ui/peaking.slint:25`](../../ui/dr-ui/ui/peaking.slint#L25), [`ui/dr-ui/ui/peaking.slint:56`](../../ui/dr-ui/ui/peaking.slint#L56), [`ui/dr-ui/ui/peaking.slint:91`](../../ui/dr-ui/ui/peaking.slint#L91) | | FR-CULL-4 | [`core/dr-catalog/src/rating.rs:1`](../../core/dr-catalog/src/rating.rs#L1), [`core/dr-pipeline/src/sidecar.rs:174`](../../core/dr-pipeline/src/sidecar.rs#L174), [`core/dr-xmp/src/lib.rs:442`](../../core/dr-xmp/src/lib.rs#L442), [`ui/dr-ui/src/library/filters.rs:64`](../../ui/dr-ui/src/library/filters.rs#L64), [`ui/dr-ui/src/library/sidecar.rs:12`](../../ui/dr-ui/src/library/sidecar.rs#L12), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1035`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1035), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1311`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1311), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:464`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L464), [`ui/dr-ui/ui/app.slint:1675`](../../ui/dr-ui/ui/app.slint#L1675), [`ui/dr-ui/ui/app.slint:2791`](../../ui/dr-ui/ui/app.slint#L2791), [`ui/dr-ui/ui/develop.slint:168`](../../ui/dr-ui/ui/develop.slint#L168), [`ui/dr-ui/ui/develop.slint:55`](../../ui/dr-ui/ui/develop.slint#L55), [`ui/dr-ui/ui/library.slint:1044`](../../ui/dr-ui/ui/library.slint#L1044), [`ui/dr-ui/ui/library.slint:1623`](../../ui/dr-ui/ui/library.slint#L1623), [`ui/dr-ui/ui/library.slint:488`](../../ui/dr-ui/ui/library.slint#L488), [`ui/dr-ui/ui/library.slint:5093`](../../ui/dr-ui/ui/library.slint#L5093), [`ui/dr-ui/ui/library.slint:647`](../../ui/dr-ui/ui/library.slint#L647) | | FR-CULL-5 | [`core/dr-catalog/src/bursts.rs:1`](../../core/dr-catalog/src/bursts.rs#L1), [`core/dr-catalog/src/schema.rs:676`](../../core/dr-catalog/src/schema.rs#L676), [`ui/dr-ui/src/bursts.rs:1`](../../ui/dr-ui/src/bursts.rs#L1), [`ui/dr-ui/src/library/cells.rs:21`](../../ui/dr-ui/src/library/cells.rs#L21), [`ui/dr-ui/src/library/cells.rs:776`](../../ui/dr-ui/src/library/cells.rs#L776), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1085`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1085), [`ui/dr-ui/ui/library.slint:488`](../../ui/dr-ui/ui/library.slint#L488) | | FR-CULL-8 | [`core/dr-catalog/src/face_shard.rs:1`](../../core/dr-catalog/src/face_shard.rs#L1), [`core/dr-catalog/src/faces.rs:1`](../../core/dr-catalog/src/faces.rs#L1), [`core/dr-catalog/src/schema.rs:1000`](../../core/dr-catalog/src/schema.rs#L1000), [`core/dr-catalog/src/schema.rs:1041`](../../core/dr-catalog/src/schema.rs#L1041), [`core/dr-catalog/src/schema.rs:744`](../../core/dr-catalog/src/schema.rs#L744), [`core/dr-face/src/align.rs:296`](../../core/dr-face/src/align.rs#L296), [`core/dr-types/src/settings.rs:176`](../../core/dr-types/src/settings.rs#L176), [`ui/dr-ui/examples/face_detectors.rs:1`](../../ui/dr-ui/examples/face_detectors.rs#L1), [`ui/dr-ui/examples/face_native.rs:1`](../../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/derived_sync.rs:128`](../../ui/dr-ui/src/derived_sync.rs#L128), [`ui/dr-ui/src/faces.rs:1`](../../ui/dr-ui/src/faces.rs#L1), [`ui/dr-ui/src/faces.rs:447`](../../ui/dr-ui/src/faces.rs#L447), [`ui/dr-ui/src/faces.rs:463`](../../ui/dr-ui/src/faces.rs#L463), [`ui/dr-ui/src/faces.rs:585`](../../ui/dr-ui/src/faces.rs#L585), [`ui/dr-ui/src/identity_ui.rs:1472`](../../ui/dr-ui/src/identity_ui.rs#L1472), [`ui/dr-ui/src/identity_ui.rs:617`](../../ui/dr-ui/src/identity_ui.rs#L617), [`ui/dr-ui/src/lib.rs:1785`](../../ui/dr-ui/src/lib.rs#L1785), [`ui/dr-ui/src/lib.rs:3113`](../../ui/dr-ui/src/lib.rs#L3113), [`ui/dr-ui/src/library/sweep.rs:243`](../../ui/dr-ui/src/library/sweep.rs#L243), [`ui/dr-ui/src/library/sweep.rs:511`](../../ui/dr-ui/src/library/sweep.rs#L511), [`ui/dr-ui/src/library_ui/controller.rs:422`](../../ui/dr-ui/src/library_ui/controller.rs#L422), [`ui/dr-ui/src/library_ui/controller.rs:512`](../../ui/dr-ui/src/library_ui/controller.rs#L512), [`ui/dr-ui/src/repairs.rs:1`](../../ui/dr-ui/src/repairs.rs#L1), [`ui/dr-ui/src/settings_ui.rs:174`](../../ui/dr-ui/src/settings_ui.rs#L174), [`ui/dr-ui/src/settings_ui.rs:537`](../../ui/dr-ui/src/settings_ui.rs#L537), [`ui/dr-ui/ui/app.slint:673`](../../ui/dr-ui/ui/app.slint#L673), [`ui/dr-ui/ui/settings.slint:101`](../../ui/dr-ui/ui/settings.slint#L101), [`ui/dr-ui/ui/settings.slint:407`](../../ui/dr-ui/ui/settings.slint#L407), [`ui/dr-ui/ui/settings.slint:469`](../../ui/dr-ui/ui/settings.slint#L469), [`ui/dr-ui/ui/settings.slint:83`](../../ui/dr-ui/ui/settings.slint#L83), [`ui/dr-ui/ui/settings.slint:95`](../../ui/dr-ui/ui/settings.slint#L95) | @@ -71,46 +71,46 @@ _None._ | FR-DEV-19 | [`core/dr-pipeline/src/mask.rs:1341`](../../core/dr-pipeline/src/mask.rs#L1341) | | FR-DEV-19a | [`core/dr-gpu/src/mask.rs:655`](../../core/dr-gpu/src/mask.rs#L655), [`core/dr-gpu/src/mask.rs:773`](../../core/dr-gpu/src/mask.rs#L773), [`core/dr-gpu/tests/local_adjustments.rs:793`](../../core/dr-gpu/tests/local_adjustments.rs#L793), [`core/dr-gpu/tests/local_adjustments.rs:841`](../../core/dr-gpu/tests/local_adjustments.rs#L841), [`core/dr-pipeline/src/mask.rs:1022`](../../core/dr-pipeline/src/mask.rs#L1022), [`core/dr-pipeline/src/mask.rs:1635`](../../core/dr-pipeline/src/mask.rs#L1635), [`core/dr-pipeline/src/mask.rs:3282`](../../core/dr-pipeline/src/mask.rs#L3282), [`core/dr-pipeline/src/mask.rs:3403`](../../core/dr-pipeline/src/mask.rs#L3403), [`core/dr-pipeline/src/mask.rs:3438`](../../core/dr-pipeline/src/mask.rs#L3438), [`core/dr-pipeline/src/mask.rs:929`](../../core/dr-pipeline/src/mask.rs#L929), [`core/dr-pipeline/src/mask.rs:964`](../../core/dr-pipeline/src/mask.rs#L964), [`core/dr-pipeline/src/sidecar.rs:1259`](../../core/dr-pipeline/src/sidecar.rs#L1259), [`core/dr-pipeline/tests/mask_sidecar.rs:1347`](../../core/dr-pipeline/tests/mask_sidecar.rs#L1347), [`core/dr-pipeline/tests/mask_sidecar.rs:1369`](../../core/dr-pipeline/tests/mask_sidecar.rs#L1369), [`core/dr-pipeline/tests/mask_sidecar.rs:1395`](../../core/dr-pipeline/tests/mask_sidecar.rs#L1395), [`ui/dr-ui/src/develop/masks.rs:432`](../../ui/dr-ui/src/develop/masks.rs#L432), [`ui/dr-ui/src/develop/masks.rs:493`](../../ui/dr-ui/src/develop/masks.rs#L493), [`ui/dr-ui/src/develop/masks.rs:512`](../../ui/dr-ui/src/develop/masks.rs#L512), [`ui/dr-ui/src/develop/masks.rs:547`](../../ui/dr-ui/src/develop/masks.rs#L547), [`ui/dr-ui/src/develop/session.rs:192`](../../ui/dr-ui/src/develop/session.rs#L192), [`ui/dr-ui/src/labels.rs:73`](../../ui/dr-ui/src/labels.rs#L73), [`ui/dr-ui/src/masks_ui.rs:1083`](../../ui/dr-ui/src/masks_ui.rs#L1083), [`ui/dr-ui/src/masks_ui.rs:1140`](../../ui/dr-ui/src/masks_ui.rs#L1140), [`ui/dr-ui/src/masks_ui.rs:1196`](../../ui/dr-ui/src/masks_ui.rs#L1196), [`ui/dr-ui/src/masks_ui.rs:1555`](../../ui/dr-ui/src/masks_ui.rs#L1555), [`ui/dr-ui/src/masks_ui.rs:1578`](../../ui/dr-ui/src/masks_ui.rs#L1578), [`ui/dr-ui/src/masks_ui.rs:270`](../../ui/dr-ui/src/masks_ui.rs#L270), [`ui/dr-ui/ui/app.slint:2639`](../../ui/dr-ui/ui/app.slint#L2639), [`ui/dr-ui/ui/masks.slint:151`](../../ui/dr-ui/ui/masks.slint#L151), [`ui/dr-ui/ui/masks.slint:176`](../../ui/dr-ui/ui/masks.slint#L176), [`ui/dr-ui/ui/masks.slint:339`](../../ui/dr-ui/ui/masks.slint#L339), [`ui/dr-ui/ui/masks.slint:379`](../../ui/dr-ui/ui/masks.slint#L379), [`ui/dr-ui/ui/masks.slint:422`](../../ui/dr-ui/ui/masks.slint#L422), [`ui/dr-ui/ui/masks.slint:468`](../../ui/dr-ui/ui/masks.slint#L468), [`ui/dr-ui/ui/masks.slint:796`](../../ui/dr-ui/ui/masks.slint#L796), [`ui/dr-ui/ui/masks.slint:881`](../../ui/dr-ui/ui/masks.slint#L881) | | FR-DEV-19b | [`ui/dr-ui/src/develop/mask_ops.rs:606`](../../ui/dr-ui/src/develop/mask_ops.rs#L606), [`ui/dr-ui/src/develop/masks.rs:595`](../../ui/dr-ui/src/develop/masks.rs#L595), [`ui/dr-ui/src/develop/session.rs:201`](../../ui/dr-ui/src/develop/session.rs#L201), [`ui/dr-ui/src/develop/session.rs:208`](../../ui/dr-ui/src/develop/session.rs#L208), [`ui/dr-ui/src/labels.rs:67`](../../ui/dr-ui/src/labels.rs#L67), [`ui/dr-ui/src/masks_ui.rs:1229`](../../ui/dr-ui/src/masks_ui.rs#L1229), [`ui/dr-ui/src/masks_ui.rs:1448`](../../ui/dr-ui/src/masks_ui.rs#L1448), [`ui/dr-ui/src/masks_ui.rs:1476`](../../ui/dr-ui/src/masks_ui.rs#L1476), [`ui/dr-ui/src/masks_ui.rs:1849`](../../ui/dr-ui/src/masks_ui.rs#L1849), [`ui/dr-ui/src/masks_ui.rs:908`](../../ui/dr-ui/src/masks_ui.rs#L908), [`ui/dr-ui/ui/app.slint:2174`](../../ui/dr-ui/ui/app.slint#L2174), [`ui/dr-ui/ui/app.slint:857`](../../ui/dr-ui/ui/app.slint#L857), [`ui/dr-ui/ui/masks.slint:1156`](../../ui/dr-ui/ui/masks.slint#L1156), [`ui/dr-ui/ui/masks.slint:479`](../../ui/dr-ui/ui/masks.slint#L479), [`ui/dr-ui/ui/masks.slint:800`](../../ui/dr-ui/ui/masks.slint#L800), [`ui/dr-ui/ui/masks.slint:874`](../../ui/dr-ui/ui/masks.slint#L874), [`ui/dr-ui/ui/masks.slint:894`](../../ui/dr-ui/ui/masks.slint#L894) | -| FR-DEV-19c | [`core/dr-gpu/src/mask.rs:727`](../../core/dr-gpu/src/mask.rs#L727), [`core/dr-gpu/tests/local_adjustments.rs:1000`](../../core/dr-gpu/tests/local_adjustments.rs#L1000), [`core/dr-gpu/tests/local_adjustments.rs:1035`](../../core/dr-gpu/tests/local_adjustments.rs#L1035), [`core/dr-gpu/tests/local_adjustments.rs:1080`](../../core/dr-gpu/tests/local_adjustments.rs#L1080), [`core/dr-gpu/tests/local_adjustments.rs:943`](../../core/dr-gpu/tests/local_adjustments.rs#L943), [`core/dr-pipeline/src/graph.rs:899`](../../core/dr-pipeline/src/graph.rs#L899), [`core/dr-pipeline/src/mask.rs:1843`](../../core/dr-pipeline/src/mask.rs#L1843), [`core/dr-pipeline/src/mask.rs:1869`](../../core/dr-pipeline/src/mask.rs#L1869), [`core/dr-pipeline/src/mask.rs:1884`](../../core/dr-pipeline/src/mask.rs#L1884), [`core/dr-pipeline/src/mask.rs:2006`](../../core/dr-pipeline/src/mask.rs#L2006), [`core/dr-pipeline/src/mask.rs:2065`](../../core/dr-pipeline/src/mask.rs#L2065), [`core/dr-pipeline/src/mask.rs:2309`](../../core/dr-pipeline/src/mask.rs#L2309), [`core/dr-pipeline/src/mask.rs:2621`](../../core/dr-pipeline/src/mask.rs#L2621), [`core/dr-pipeline/src/operation.rs:1019`](../../core/dr-pipeline/src/operation.rs#L1019), [`core/dr-pipeline/src/operation.rs:1989`](../../core/dr-pipeline/src/operation.rs#L1989), [`core/dr-pipeline/src/operation.rs:683`](../../core/dr-pipeline/src/operation.rs#L683), [`ui/dr-ui/src/develop/mask_ops.rs:1199`](../../ui/dr-ui/src/develop/mask_ops.rs#L1199), [`ui/dr-ui/src/develop/mask_ops.rs:1235`](../../ui/dr-ui/src/develop/mask_ops.rs#L1235), [`ui/dr-ui/src/develop/mask_ops.rs:318`](../../ui/dr-ui/src/develop/mask_ops.rs#L318), [`ui/dr-ui/src/develop/mask_ops.rs:58`](../../ui/dr-ui/src/develop/mask_ops.rs#L58), [`ui/dr-ui/src/develop/masks.rs:12`](../../ui/dr-ui/src/develop/masks.rs#L12), [`ui/dr-ui/src/develop/masks.rs:176`](../../ui/dr-ui/src/develop/masks.rs#L176), [`ui/dr-ui/src/develop/masks.rs:21`](../../ui/dr-ui/src/develop/masks.rs#L21), [`ui/dr-ui/src/develop/masks.rs:43`](../../ui/dr-ui/src/develop/masks.rs#L43), [`ui/dr-ui/src/develop/render.rs:260`](../../ui/dr-ui/src/develop/render.rs#L260), [`ui/dr-ui/src/develop/session.rs:227`](../../ui/dr-ui/src/develop/session.rs#L227), [`ui/dr-ui/src/develop/session.rs:236`](../../ui/dr-ui/src/develop/session.rs#L236), [`ui/dr-ui/src/masks_ui.rs:1024`](../../ui/dr-ui/src/masks_ui.rs#L1024), [`ui/dr-ui/src/masks_ui.rs:1448`](../../ui/dr-ui/src/masks_ui.rs#L1448), [`ui/dr-ui/src/masks_ui.rs:152`](../../ui/dr-ui/src/masks_ui.rs#L152), [`ui/dr-ui/src/masks_ui.rs:1849`](../../ui/dr-ui/src/masks_ui.rs#L1849), [`ui/dr-ui/src/masks_ui.rs:291`](../../ui/dr-ui/src/masks_ui.rs#L291), [`ui/dr-ui/src/masks_ui.rs:317`](../../ui/dr-ui/src/masks_ui.rs#L317), [`ui/dr-ui/src/masks_ui.rs:677`](../../ui/dr-ui/src/masks_ui.rs#L677), [`ui/dr-ui/src/masks_ui.rs:996`](../../ui/dr-ui/src/masks_ui.rs#L996), [`ui/dr-ui/ui/icons.slint:340`](../../ui/dr-ui/ui/icons.slint#L340), [`ui/dr-ui/ui/masks.slint:1121`](../../ui/dr-ui/ui/masks.slint#L1121), [`ui/dr-ui/ui/masks.slint:184`](../../ui/dr-ui/ui/masks.slint#L184), [`ui/dr-ui/ui/masks.slint:294`](../../ui/dr-ui/ui/masks.slint#L294), [`ui/dr-ui/ui/masks.slint:543`](../../ui/dr-ui/ui/masks.slint#L543), [`ui/dr-ui/ui/masks.slint:70`](../../ui/dr-ui/ui/masks.slint#L70), [`ui/dr-ui/ui/masks.slint:808`](../../ui/dr-ui/ui/masks.slint#L808), [`ui/dr-ui/ui/masks.slint:876`](../../ui/dr-ui/ui/masks.slint#L876), [`ui/dr-ui/ui/masks.slint:968`](../../ui/dr-ui/ui/masks.slint#L968) | -| FR-DEV-2 | [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:88`](../../core/dr-gpu/tests/view_transform.rs#L88), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2296`](../../core/dr-pipeline/src/operation.rs#L2296), [`core/dr-pipeline/src/operation.rs:357`](../../core/dr-pipeline/src/operation.rs#L357), [`core/dr-pipeline/src/operation.rs:431`](../../core/dr-pipeline/src/operation.rs#L431), [`core/dr-pipeline/src/operation.rs:451`](../../core/dr-pipeline/src/operation.rs#L451), [`core/dr-pipeline/src/operation.rs:490`](../../core/dr-pipeline/src/operation.rs#L490), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211) | -| FR-DEV-20 | [`core/dr-gpu/src/adjust.rs:2165`](../../core/dr-gpu/src/adjust.rs#L2165), [`core/dr-pipeline/src/framing.rs:1362`](../../core/dr-pipeline/src/framing.rs#L1362), [`core/dr-pipeline/src/framing.rs:170`](../../core/dr-pipeline/src/framing.rs#L170), [`core/dr-pipeline/src/framing.rs:388`](../../core/dr-pipeline/src/framing.rs#L388), [`core/dr-pipeline/src/framing.rs:482`](../../core/dr-pipeline/src/framing.rs#L482), [`core/dr-pipeline/src/framing.rs:639`](../../core/dr-pipeline/src/framing.rs#L639), [`core/dr-pipeline/src/framing.rs:650`](../../core/dr-pipeline/src/framing.rs#L650), [`core/dr-pipeline/src/framing.rs:88`](../../core/dr-pipeline/src/framing.rs#L88), [`core/dr-pipeline/src/framing.rs:925`](../../core/dr-pipeline/src/framing.rs#L925), [`core/dr-pipeline/src/framing.rs:92`](../../core/dr-pipeline/src/framing.rs#L92), [`core/dr-pipeline/src/framing.rs:981`](../../core/dr-pipeline/src/framing.rs#L981), [`core/dr-pipeline/src/preset.rs:1001`](../../core/dr-pipeline/src/preset.rs#L1001), [`core/dr-pipeline/src/sidecar.rs:2197`](../../core/dr-pipeline/src/sidecar.rs#L2197), [`ui/dr-ui/src/develop/framing.rs:1035`](../../ui/dr-ui/src/develop/framing.rs#L1035), [`ui/dr-ui/src/develop/framing.rs:418`](../../ui/dr-ui/src/develop/framing.rs#L418), [`ui/dr-ui/src/develop/framing.rs:474`](../../ui/dr-ui/src/develop/framing.rs#L474), [`ui/dr-ui/src/develop/framing.rs:480`](../../ui/dr-ui/src/develop/framing.rs#L480), [`ui/dr-ui/src/develop/framing.rs:489`](../../ui/dr-ui/src/develop/framing.rs#L489), [`ui/dr-ui/src/develop_ui.rs:1300`](../../ui/dr-ui/src/develop_ui.rs#L1300), [`ui/dr-ui/src/develop_ui.rs:1333`](../../ui/dr-ui/src/develop_ui.rs#L1333), [`ui/dr-ui/src/labels.rs:285`](../../ui/dr-ui/src/labels.rs#L285), [`ui/dr-ui/ui/adjust.slint:646`](../../ui/dr-ui/ui/adjust.slint#L646), [`ui/dr-ui/ui/adjust.slint:688`](../../ui/dr-ui/ui/adjust.slint#L688), [`ui/dr-ui/ui/adjust.slint:831`](../../ui/dr-ui/ui/adjust.slint#L831), [`ui/dr-ui/ui/app.slint:2663`](../../ui/dr-ui/ui/app.slint#L2663), [`ui/dr-ui/ui/app.slint:723`](../../ui/dr-ui/ui/app.slint#L723), [`ui/dr-ui/ui/app.slint:746`](../../ui/dr-ui/ui/app.slint#L746) | -| FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:1047`](../../core/dr-gpu/src/adjust.rs#L1047), [`core/dr-gpu/src/adjust.rs:2769`](../../core/dr-gpu/src/adjust.rs#L2769), [`core/dr-gpu/src/adjust.rs:74`](../../core/dr-gpu/src/adjust.rs#L74), [`core/dr-gpu/src/adjust.rs:914`](../../core/dr-gpu/src/adjust.rs#L914), [`core/dr-gpu/tests/tone_curve.rs:1`](../../core/dr-gpu/tests/tone_curve.rs#L1), [`core/dr-pipeline/src/coverage.rs:122`](../../core/dr-pipeline/src/coverage.rs#L122), [`core/dr-pipeline/src/coverage.rs:1`](../../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/detail.rs:452`](../../core/dr-pipeline/src/detail.rs#L452), [`core/dr-pipeline/src/detail.rs:542`](../../core/dr-pipeline/src/detail.rs#L542), [`core/dr-pipeline/src/framing.rs:1098`](../../core/dr-pipeline/src/framing.rs#L1098), [`core/dr-pipeline/src/framing.rs:251`](../../core/dr-pipeline/src/framing.rs#L251), [`core/dr-pipeline/src/framing.rs:308`](../../core/dr-pipeline/src/framing.rs#L308), [`core/dr-pipeline/src/framing.rs:468`](../../core/dr-pipeline/src/framing.rs#L468), [`core/dr-pipeline/src/framing.rs:704`](../../core/dr-pipeline/src/framing.rs#L704), [`core/dr-pipeline/src/graph.rs:1364`](../../core/dr-pipeline/src/graph.rs#L1364), [`core/dr-pipeline/src/graph.rs:1395`](../../core/dr-pipeline/src/graph.rs#L1395), [`core/dr-pipeline/src/graph.rs:1418`](../../core/dr-pipeline/src/graph.rs#L1418), [`core/dr-pipeline/src/graph.rs:1456`](../../core/dr-pipeline/src/graph.rs#L1456), [`core/dr-pipeline/src/graph.rs:1487`](../../core/dr-pipeline/src/graph.rs#L1487), [`core/dr-pipeline/src/graph.rs:225`](../../core/dr-pipeline/src/graph.rs#L225), [`core/dr-pipeline/src/graph.rs:306`](../../core/dr-pipeline/src/graph.rs#L306), [`core/dr-pipeline/src/graph.rs:344`](../../core/dr-pipeline/src/graph.rs#L344), [`core/dr-pipeline/src/graph.rs:350`](../../core/dr-pipeline/src/graph.rs#L350), [`core/dr-pipeline/src/graph.rs:866`](../../core/dr-pipeline/src/graph.rs#L866), [`core/dr-pipeline/src/graph.rs:958`](../../core/dr-pipeline/src/graph.rs#L958), [`core/dr-pipeline/src/lens.rs:93`](../../core/dr-pipeline/src/lens.rs#L93), [`core/dr-pipeline/src/mask.rs:205`](../../core/dr-pipeline/src/mask.rs#L205), [`core/dr-pipeline/src/mask.rs:558`](../../core/dr-pipeline/src/mask.rs#L558), [`core/dr-pipeline/src/neutral.rs:1`](../../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:306`](../../core/dr-pipeline/src/neutral.rs#L306), [`core/dr-pipeline/src/neutral.rs:322`](../../core/dr-pipeline/src/neutral.rs#L322), [`core/dr-pipeline/src/neutral.rs:338`](../../core/dr-pipeline/src/neutral.rs#L338), [`core/dr-pipeline/src/neutral.rs:360`](../../core/dr-pipeline/src/neutral.rs#L360), [`core/dr-pipeline/src/neutral.rs:81`](../../core/dr-pipeline/src/neutral.rs#L81), [`core/dr-pipeline/src/operation.rs:321`](../../core/dr-pipeline/src/operation.rs#L321), [`core/dr-pipeline/src/operation.rs:365`](../../core/dr-pipeline/src/operation.rs#L365), [`core/dr-pipeline/src/operation.rs:659`](../../core/dr-pipeline/src/operation.rs#L659), [`core/dr-pipeline/src/operation.rs:732`](../../core/dr-pipeline/src/operation.rs#L732), [`core/dr-pipeline/src/operation.rs:895`](../../core/dr-pipeline/src/operation.rs#L895), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:210`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L210), [`core/dr-pipeline/src/ops/curve.rs:100`](../../core/dr-pipeline/src/ops/curve.rs#L100), [`core/dr-pipeline/src/ops/curve.rs:1`](../../core/dr-pipeline/src/ops/curve.rs#L1), [`core/dr-pipeline/src/ops/curve.rs:219`](../../core/dr-pipeline/src/ops/curve.rs#L219), [`core/dr-pipeline/src/ops/curve.rs:635`](../../core/dr-pipeline/src/ops/curve.rs#L635), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:1`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:273`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L273), [`core/dr-pipeline/src/preset.rs:927`](../../core/dr-pipeline/src/preset.rs#L927), [`core/dr-pipeline/src/sidecar.rs:1433`](../../core/dr-pipeline/src/sidecar.rs#L1433), [`core/dr-pipeline/src/sidecar.rs:206`](../../core/dr-pipeline/src/sidecar.rs#L206), [`core/dr-pipeline/src/sidecar.rs:2275`](../../core/dr-pipeline/src/sidecar.rs#L2275), [`core/dr-pipeline/src/sidecar.rs:2355`](../../core/dr-pipeline/src/sidecar.rs#L2355), [`core/dr-pipeline/tests/tone_curve.rs:1`](../../core/dr-pipeline/tests/tone_curve.rs#L1), [`core/dr-segment/src/refine.rs:937`](../../core/dr-segment/src/refine.rs#L937), [`ui/dr-ui/src/develop/curves.rs:163`](../../ui/dr-ui/src/develop/curves.rs#L163), [`ui/dr-ui/src/develop/framing.rs:10`](../../ui/dr-ui/src/develop/framing.rs#L10), [`ui/dr-ui/src/develop/framing.rs:298`](../../ui/dr-ui/src/develop/framing.rs#L298), [`ui/dr-ui/src/develop/framing.rs:328`](../../ui/dr-ui/src/develop/framing.rs#L328), [`ui/dr-ui/src/develop/framing.rs:394`](../../ui/dr-ui/src/develop/framing.rs#L394), [`ui/dr-ui/src/develop/framing.rs:408`](../../ui/dr-ui/src/develop/framing.rs#L408), [`ui/dr-ui/src/develop/framing.rs:644`](../../ui/dr-ui/src/develop/framing.rs#L644), [`ui/dr-ui/src/develop/framing.rs:71`](../../ui/dr-ui/src/develop/framing.rs#L71), [`ui/dr-ui/src/develop/mask_ops.rs:1076`](../../ui/dr-ui/src/develop/mask_ops.rs#L1076), [`ui/dr-ui/src/develop/mask_ops.rs:1340`](../../ui/dr-ui/src/develop/mask_ops.rs#L1340), [`ui/dr-ui/src/develop/mask_ops.rs:178`](../../ui/dr-ui/src/develop/mask_ops.rs#L178), [`ui/dr-ui/src/develop/mask_ops.rs:969`](../../ui/dr-ui/src/develop/mask_ops.rs#L969), [`ui/dr-ui/src/develop/masks.rs:263`](../../ui/dr-ui/src/develop/masks.rs#L263), [`ui/dr-ui/src/develop/masks.rs:361`](../../ui/dr-ui/src/develop/masks.rs#L361), [`ui/dr-ui/src/develop/masks.rs:743`](../../ui/dr-ui/src/develop/masks.rs#L743), [`ui/dr-ui/src/develop/masks.rs:773`](../../ui/dr-ui/src/develop/masks.rs#L773), [`ui/dr-ui/src/develop/render.rs:1244`](../../ui/dr-ui/src/develop/render.rs#L1244), [`ui/dr-ui/src/develop/rows.rs:106`](../../ui/dr-ui/src/develop/rows.rs#L106), [`ui/dr-ui/src/develop/rows.rs:195`](../../ui/dr-ui/src/develop/rows.rs#L195), [`ui/dr-ui/src/develop/rows.rs:231`](../../ui/dr-ui/src/develop/rows.rs#L231), [`ui/dr-ui/src/develop/rows.rs:679`](../../ui/dr-ui/src/develop/rows.rs#L679), [`ui/dr-ui/src/develop/segmentation.rs:139`](../../ui/dr-ui/src/develop/segmentation.rs#L139), [`ui/dr-ui/src/develop/segmentation.rs:302`](../../ui/dr-ui/src/develop/segmentation.rs#L302), [`ui/dr-ui/src/develop/segmentation.rs:339`](../../ui/dr-ui/src/develop/segmentation.rs#L339), [`ui/dr-ui/src/develop/segmentation.rs:572`](../../ui/dr-ui/src/develop/segmentation.rs#L572), [`ui/dr-ui/src/develop/segmentation.rs:590`](../../ui/dr-ui/src/develop/segmentation.rs#L590), [`ui/dr-ui/src/develop/segmentation.rs:604`](../../ui/dr-ui/src/develop/segmentation.rs#L604), [`ui/dr-ui/src/develop/segmentation.rs:626`](../../ui/dr-ui/src/develop/segmentation.rs#L626), [`ui/dr-ui/src/develop/segmentation.rs:77`](../../ui/dr-ui/src/develop/segmentation.rs#L77), [`ui/dr-ui/src/develop/segmentation.rs:806`](../../ui/dr-ui/src/develop/segmentation.rs#L806), [`ui/dr-ui/src/develop/session.rs:162`](../../ui/dr-ui/src/develop/session.rs#L162), [`ui/dr-ui/src/develop/session.rs:255`](../../ui/dr-ui/src/develop/session.rs#L255), [`ui/dr-ui/src/develop/session.rs:284`](../../ui/dr-ui/src/develop/session.rs#L284), [`ui/dr-ui/src/develop/session.rs:434`](../../ui/dr-ui/src/develop/session.rs#L434), [`ui/dr-ui/src/develop/session.rs:494`](../../ui/dr-ui/src/develop/session.rs#L494), [`ui/dr-ui/src/develop/session.rs:566`](../../ui/dr-ui/src/develop/session.rs#L566), [`ui/dr-ui/src/develop/session.rs:721`](../../ui/dr-ui/src/develop/session.rs#L721), [`ui/dr-ui/src/develop/white_balance.rs:11`](../../ui/dr-ui/src/develop/white_balance.rs#L11), [`ui/dr-ui/src/develop/white_balance.rs:162`](../../ui/dr-ui/src/develop/white_balance.rs#L162), [`ui/dr-ui/src/develop/white_balance.rs:193`](../../ui/dr-ui/src/develop/white_balance.rs#L193), [`ui/dr-ui/src/develop/white_balance.rs:275`](../../ui/dr-ui/src/develop/white_balance.rs#L275), [`ui/dr-ui/src/develop/white_balance.rs:336`](../../ui/dr-ui/src/develop/white_balance.rs#L336), [`ui/dr-ui/src/develop_ui.rs:1113`](../../ui/dr-ui/src/develop_ui.rs#L1113), [`ui/dr-ui/src/develop_ui.rs:117`](../../ui/dr-ui/src/develop_ui.rs#L117), [`ui/dr-ui/src/develop_ui.rs:1210`](../../ui/dr-ui/src/develop_ui.rs#L1210), [`ui/dr-ui/src/develop_ui.rs:1264`](../../ui/dr-ui/src/develop_ui.rs#L1264), [`ui/dr-ui/src/develop_ui.rs:514`](../../ui/dr-ui/src/develop_ui.rs#L514), [`ui/dr-ui/src/develop_ui.rs:734`](../../ui/dr-ui/src/develop_ui.rs#L734), [`ui/dr-ui/src/labels.rs:35`](../../ui/dr-ui/src/labels.rs#L35), [`ui/dr-ui/src/lib.rs:2155`](../../ui/dr-ui/src/lib.rs#L2155), [`ui/dr-ui/src/lib.rs:456`](../../ui/dr-ui/src/lib.rs#L456), [`ui/dr-ui/src/lib.rs:486`](../../ui/dr-ui/src/lib.rs#L486), [`ui/dr-ui/src/lib.rs:594`](../../ui/dr-ui/src/lib.rs#L594), [`ui/dr-ui/src/lib.rs:618`](../../ui/dr-ui/src/lib.rs#L618), [`ui/dr-ui/src/library/sidecar.rs:66`](../../ui/dr-ui/src/library/sidecar.rs#L66), [`ui/dr-ui/src/masks_ui.rs:1608`](../../ui/dr-ui/src/masks_ui.rs#L1608), [`ui/dr-ui/src/masks_ui.rs:1722`](../../ui/dr-ui/src/masks_ui.rs#L1722), [`ui/dr-ui/src/masks_ui.rs:339`](../../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/masks_ui.rs:44`](../../ui/dr-ui/src/masks_ui.rs#L44), [`ui/dr-ui/src/presets.rs:414`](../../ui/dr-ui/src/presets.rs#L414), [`ui/dr-ui/src/segmentation.rs:117`](../../ui/dr-ui/src/segmentation.rs#L117), [`ui/dr-ui/src/segmentation.rs:353`](../../ui/dr-ui/src/segmentation.rs#L353), [`ui/dr-ui/src/segmentation.rs:369`](../../ui/dr-ui/src/segmentation.rs#L369), [`ui/dr-ui/src/segmentation.rs:499`](../../ui/dr-ui/src/segmentation.rs#L499), [`ui/dr-ui/src/segmentation.rs:527`](../../ui/dr-ui/src/segmentation.rs#L527), [`ui/dr-ui/ui/adjust.slint:1050`](../../ui/dr-ui/ui/adjust.slint#L1050), [`ui/dr-ui/ui/adjust.slint:127`](../../ui/dr-ui/ui/adjust.slint#L127), [`ui/dr-ui/ui/adjust.slint:1658`](../../ui/dr-ui/ui/adjust.slint#L1658), [`ui/dr-ui/ui/adjust.slint:173`](../../ui/dr-ui/ui/adjust.slint#L173), [`ui/dr-ui/ui/adjust.slint:47`](../../ui/dr-ui/ui/adjust.slint#L47), [`ui/dr-ui/ui/adjust.slint:626`](../../ui/dr-ui/ui/adjust.slint#L626), [`ui/dr-ui/ui/adjust.slint:662`](../../ui/dr-ui/ui/adjust.slint#L662), [`ui/dr-ui/ui/adjust.slint:681`](../../ui/dr-ui/ui/adjust.slint#L681), [`ui/dr-ui/ui/adjust.slint:874`](../../ui/dr-ui/ui/adjust.slint#L874), [`ui/dr-ui/ui/adjust.slint:973`](../../ui/dr-ui/ui/adjust.slint#L973), [`ui/dr-ui/ui/app.slint:2239`](../../ui/dr-ui/ui/app.slint#L2239), [`ui/dr-ui/ui/app.slint:2301`](../../ui/dr-ui/ui/app.slint#L2301), [`ui/dr-ui/ui/app.slint:242`](../../ui/dr-ui/ui/app.slint#L242), [`ui/dr-ui/ui/develop.slint:375`](../../ui/dr-ui/ui/develop.slint#L375), [`ui/dr-ui/ui/masks.slint:1246`](../../ui/dr-ui/ui/masks.slint#L1246), [`ui/dr-ui/ui/masks.slint:779`](../../ui/dr-ui/ui/masks.slint#L779), [`ui/dr-ui/ui/masks.slint:838`](../../ui/dr-ui/ui/masks.slint#L838) | +| FR-DEV-19c | [`core/dr-gpu/src/mask.rs:727`](../../core/dr-gpu/src/mask.rs#L727), [`core/dr-gpu/tests/local_adjustments.rs:1000`](../../core/dr-gpu/tests/local_adjustments.rs#L1000), [`core/dr-gpu/tests/local_adjustments.rs:1035`](../../core/dr-gpu/tests/local_adjustments.rs#L1035), [`core/dr-gpu/tests/local_adjustments.rs:1080`](../../core/dr-gpu/tests/local_adjustments.rs#L1080), [`core/dr-gpu/tests/local_adjustments.rs:943`](../../core/dr-gpu/tests/local_adjustments.rs#L943), [`core/dr-pipeline/src/graph.rs:899`](../../core/dr-pipeline/src/graph.rs#L899), [`core/dr-pipeline/src/mask.rs:1843`](../../core/dr-pipeline/src/mask.rs#L1843), [`core/dr-pipeline/src/mask.rs:1869`](../../core/dr-pipeline/src/mask.rs#L1869), [`core/dr-pipeline/src/mask.rs:1884`](../../core/dr-pipeline/src/mask.rs#L1884), [`core/dr-pipeline/src/mask.rs:2006`](../../core/dr-pipeline/src/mask.rs#L2006), [`core/dr-pipeline/src/mask.rs:2065`](../../core/dr-pipeline/src/mask.rs#L2065), [`core/dr-pipeline/src/mask.rs:2309`](../../core/dr-pipeline/src/mask.rs#L2309), [`core/dr-pipeline/src/mask.rs:2621`](../../core/dr-pipeline/src/mask.rs#L2621), [`core/dr-pipeline/src/operation.rs:1051`](../../core/dr-pipeline/src/operation.rs#L1051), [`core/dr-pipeline/src/operation.rs:2062`](../../core/dr-pipeline/src/operation.rs#L2062), [`core/dr-pipeline/src/operation.rs:694`](../../core/dr-pipeline/src/operation.rs#L694), [`ui/dr-ui/src/develop/mask_ops.rs:1199`](../../ui/dr-ui/src/develop/mask_ops.rs#L1199), [`ui/dr-ui/src/develop/mask_ops.rs:1235`](../../ui/dr-ui/src/develop/mask_ops.rs#L1235), [`ui/dr-ui/src/develop/mask_ops.rs:318`](../../ui/dr-ui/src/develop/mask_ops.rs#L318), [`ui/dr-ui/src/develop/mask_ops.rs:58`](../../ui/dr-ui/src/develop/mask_ops.rs#L58), [`ui/dr-ui/src/develop/masks.rs:12`](../../ui/dr-ui/src/develop/masks.rs#L12), [`ui/dr-ui/src/develop/masks.rs:176`](../../ui/dr-ui/src/develop/masks.rs#L176), [`ui/dr-ui/src/develop/masks.rs:21`](../../ui/dr-ui/src/develop/masks.rs#L21), [`ui/dr-ui/src/develop/masks.rs:43`](../../ui/dr-ui/src/develop/masks.rs#L43), [`ui/dr-ui/src/develop/render.rs:256`](../../ui/dr-ui/src/develop/render.rs#L256), [`ui/dr-ui/src/develop/session.rs:227`](../../ui/dr-ui/src/develop/session.rs#L227), [`ui/dr-ui/src/develop/session.rs:236`](../../ui/dr-ui/src/develop/session.rs#L236), [`ui/dr-ui/src/masks_ui.rs:1024`](../../ui/dr-ui/src/masks_ui.rs#L1024), [`ui/dr-ui/src/masks_ui.rs:1448`](../../ui/dr-ui/src/masks_ui.rs#L1448), [`ui/dr-ui/src/masks_ui.rs:152`](../../ui/dr-ui/src/masks_ui.rs#L152), [`ui/dr-ui/src/masks_ui.rs:1849`](../../ui/dr-ui/src/masks_ui.rs#L1849), [`ui/dr-ui/src/masks_ui.rs:291`](../../ui/dr-ui/src/masks_ui.rs#L291), [`ui/dr-ui/src/masks_ui.rs:317`](../../ui/dr-ui/src/masks_ui.rs#L317), [`ui/dr-ui/src/masks_ui.rs:677`](../../ui/dr-ui/src/masks_ui.rs#L677), [`ui/dr-ui/src/masks_ui.rs:996`](../../ui/dr-ui/src/masks_ui.rs#L996), [`ui/dr-ui/ui/icons.slint:340`](../../ui/dr-ui/ui/icons.slint#L340), [`ui/dr-ui/ui/masks.slint:1121`](../../ui/dr-ui/ui/masks.slint#L1121), [`ui/dr-ui/ui/masks.slint:184`](../../ui/dr-ui/ui/masks.slint#L184), [`ui/dr-ui/ui/masks.slint:294`](../../ui/dr-ui/ui/masks.slint#L294), [`ui/dr-ui/ui/masks.slint:543`](../../ui/dr-ui/ui/masks.slint#L543), [`ui/dr-ui/ui/masks.slint:70`](../../ui/dr-ui/ui/masks.slint#L70), [`ui/dr-ui/ui/masks.slint:808`](../../ui/dr-ui/ui/masks.slint#L808), [`ui/dr-ui/ui/masks.slint:876`](../../ui/dr-ui/ui/masks.slint#L876), [`ui/dr-ui/ui/masks.slint:968`](../../ui/dr-ui/ui/masks.slint#L968) | +| FR-DEV-2 | [`core/dr-gpu/tests/view_transform.rs:152`](../../core/dr-gpu/tests/view_transform.rs#L152), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:88`](../../core/dr-gpu/tests/view_transform.rs#L88), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2369`](../../core/dr-pipeline/src/operation.rs#L2369), [`core/dr-pipeline/src/operation.rs:2590`](../../core/dr-pipeline/src/operation.rs#L2590), [`core/dr-pipeline/src/operation.rs:357`](../../core/dr-pipeline/src/operation.rs#L357), [`core/dr-pipeline/src/operation.rs:431`](../../core/dr-pipeline/src/operation.rs#L431), [`core/dr-pipeline/src/operation.rs:451`](../../core/dr-pipeline/src/operation.rs#L451), [`core/dr-pipeline/src/operation.rs:490`](../../core/dr-pipeline/src/operation.rs#L490), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211) | +| FR-DEV-20 | [`core/dr-gpu/src/adjust.rs:2257`](../../core/dr-gpu/src/adjust.rs#L2257), [`core/dr-pipeline/src/framing.rs:1362`](../../core/dr-pipeline/src/framing.rs#L1362), [`core/dr-pipeline/src/framing.rs:170`](../../core/dr-pipeline/src/framing.rs#L170), [`core/dr-pipeline/src/framing.rs:388`](../../core/dr-pipeline/src/framing.rs#L388), [`core/dr-pipeline/src/framing.rs:482`](../../core/dr-pipeline/src/framing.rs#L482), [`core/dr-pipeline/src/framing.rs:639`](../../core/dr-pipeline/src/framing.rs#L639), [`core/dr-pipeline/src/framing.rs:650`](../../core/dr-pipeline/src/framing.rs#L650), [`core/dr-pipeline/src/framing.rs:88`](../../core/dr-pipeline/src/framing.rs#L88), [`core/dr-pipeline/src/framing.rs:925`](../../core/dr-pipeline/src/framing.rs#L925), [`core/dr-pipeline/src/framing.rs:92`](../../core/dr-pipeline/src/framing.rs#L92), [`core/dr-pipeline/src/framing.rs:981`](../../core/dr-pipeline/src/framing.rs#L981), [`core/dr-pipeline/src/preset.rs:1001`](../../core/dr-pipeline/src/preset.rs#L1001), [`core/dr-pipeline/src/sidecar.rs:2197`](../../core/dr-pipeline/src/sidecar.rs#L2197), [`ui/dr-ui/src/develop/framing.rs:1035`](../../ui/dr-ui/src/develop/framing.rs#L1035), [`ui/dr-ui/src/develop/framing.rs:418`](../../ui/dr-ui/src/develop/framing.rs#L418), [`ui/dr-ui/src/develop/framing.rs:474`](../../ui/dr-ui/src/develop/framing.rs#L474), [`ui/dr-ui/src/develop/framing.rs:480`](../../ui/dr-ui/src/develop/framing.rs#L480), [`ui/dr-ui/src/develop/framing.rs:489`](../../ui/dr-ui/src/develop/framing.rs#L489), [`ui/dr-ui/src/develop_ui.rs:1300`](../../ui/dr-ui/src/develop_ui.rs#L1300), [`ui/dr-ui/src/develop_ui.rs:1333`](../../ui/dr-ui/src/develop_ui.rs#L1333), [`ui/dr-ui/src/labels.rs:285`](../../ui/dr-ui/src/labels.rs#L285), [`ui/dr-ui/ui/adjust.slint:646`](../../ui/dr-ui/ui/adjust.slint#L646), [`ui/dr-ui/ui/adjust.slint:688`](../../ui/dr-ui/ui/adjust.slint#L688), [`ui/dr-ui/ui/adjust.slint:831`](../../ui/dr-ui/ui/adjust.slint#L831), [`ui/dr-ui/ui/app.slint:2663`](../../ui/dr-ui/ui/app.slint#L2663), [`ui/dr-ui/ui/app.slint:723`](../../ui/dr-ui/ui/app.slint#L723), [`ui/dr-ui/ui/app.slint:746`](../../ui/dr-ui/ui/app.slint#L746) | +| FR-DEV-3 | [`core/dr-gpu/src/adjust.rs:1050`](../../core/dr-gpu/src/adjust.rs#L1050), [`core/dr-gpu/src/adjust.rs:2861`](../../core/dr-gpu/src/adjust.rs#L2861), [`core/dr-gpu/src/adjust.rs:74`](../../core/dr-gpu/src/adjust.rs#L74), [`core/dr-gpu/src/adjust.rs:917`](../../core/dr-gpu/src/adjust.rs#L917), [`core/dr-gpu/tests/tone_curve.rs:1`](../../core/dr-gpu/tests/tone_curve.rs#L1), [`core/dr-pipeline/src/coverage.rs:122`](../../core/dr-pipeline/src/coverage.rs#L122), [`core/dr-pipeline/src/coverage.rs:1`](../../core/dr-pipeline/src/coverage.rs#L1), [`core/dr-pipeline/src/detail.rs:450`](../../core/dr-pipeline/src/detail.rs#L450), [`core/dr-pipeline/src/detail.rs:531`](../../core/dr-pipeline/src/detail.rs#L531), [`core/dr-pipeline/src/framing.rs:1098`](../../core/dr-pipeline/src/framing.rs#L1098), [`core/dr-pipeline/src/framing.rs:251`](../../core/dr-pipeline/src/framing.rs#L251), [`core/dr-pipeline/src/framing.rs:308`](../../core/dr-pipeline/src/framing.rs#L308), [`core/dr-pipeline/src/framing.rs:468`](../../core/dr-pipeline/src/framing.rs#L468), [`core/dr-pipeline/src/framing.rs:704`](../../core/dr-pipeline/src/framing.rs#L704), [`core/dr-pipeline/src/graph.rs:1353`](../../core/dr-pipeline/src/graph.rs#L1353), [`core/dr-pipeline/src/graph.rs:1384`](../../core/dr-pipeline/src/graph.rs#L1384), [`core/dr-pipeline/src/graph.rs:1407`](../../core/dr-pipeline/src/graph.rs#L1407), [`core/dr-pipeline/src/graph.rs:1445`](../../core/dr-pipeline/src/graph.rs#L1445), [`core/dr-pipeline/src/graph.rs:1476`](../../core/dr-pipeline/src/graph.rs#L1476), [`core/dr-pipeline/src/graph.rs:225`](../../core/dr-pipeline/src/graph.rs#L225), [`core/dr-pipeline/src/graph.rs:306`](../../core/dr-pipeline/src/graph.rs#L306), [`core/dr-pipeline/src/graph.rs:344`](../../core/dr-pipeline/src/graph.rs#L344), [`core/dr-pipeline/src/graph.rs:350`](../../core/dr-pipeline/src/graph.rs#L350), [`core/dr-pipeline/src/graph.rs:866`](../../core/dr-pipeline/src/graph.rs#L866), [`core/dr-pipeline/src/graph.rs:958`](../../core/dr-pipeline/src/graph.rs#L958), [`core/dr-pipeline/src/lens.rs:93`](../../core/dr-pipeline/src/lens.rs#L93), [`core/dr-pipeline/src/mask.rs:205`](../../core/dr-pipeline/src/mask.rs#L205), [`core/dr-pipeline/src/mask.rs:558`](../../core/dr-pipeline/src/mask.rs#L558), [`core/dr-pipeline/src/neutral.rs:1`](../../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:306`](../../core/dr-pipeline/src/neutral.rs#L306), [`core/dr-pipeline/src/neutral.rs:322`](../../core/dr-pipeline/src/neutral.rs#L322), [`core/dr-pipeline/src/neutral.rs:338`](../../core/dr-pipeline/src/neutral.rs#L338), [`core/dr-pipeline/src/neutral.rs:360`](../../core/dr-pipeline/src/neutral.rs#L360), [`core/dr-pipeline/src/neutral.rs:81`](../../core/dr-pipeline/src/neutral.rs#L81), [`core/dr-pipeline/src/operation.rs:321`](../../core/dr-pipeline/src/operation.rs#L321), [`core/dr-pipeline/src/operation.rs:365`](../../core/dr-pipeline/src/operation.rs#L365), [`core/dr-pipeline/src/operation.rs:670`](../../core/dr-pipeline/src/operation.rs#L670), [`core/dr-pipeline/src/operation.rs:743`](../../core/dr-pipeline/src/operation.rs#L743), [`core/dr-pipeline/src/operation.rs:922`](../../core/dr-pipeline/src/operation.rs#L922), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:210`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L210), [`core/dr-pipeline/src/ops/curve.rs:100`](../../core/dr-pipeline/src/ops/curve.rs#L100), [`core/dr-pipeline/src/ops/curve.rs:1`](../../core/dr-pipeline/src/ops/curve.rs#L1), [`core/dr-pipeline/src/ops/curve.rs:219`](../../core/dr-pipeline/src/ops/curve.rs#L219), [`core/dr-pipeline/src/ops/curve.rs:635`](../../core/dr-pipeline/src/ops/curve.rs#L635), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:1`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L1), [`core/dr-pipeline/src/ops/noise_reduction.rs:273`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L273), [`core/dr-pipeline/src/preset.rs:927`](../../core/dr-pipeline/src/preset.rs#L927), [`core/dr-pipeline/src/sidecar.rs:1433`](../../core/dr-pipeline/src/sidecar.rs#L1433), [`core/dr-pipeline/src/sidecar.rs:206`](../../core/dr-pipeline/src/sidecar.rs#L206), [`core/dr-pipeline/src/sidecar.rs:2275`](../../core/dr-pipeline/src/sidecar.rs#L2275), [`core/dr-pipeline/src/sidecar.rs:2355`](../../core/dr-pipeline/src/sidecar.rs#L2355), [`core/dr-pipeline/tests/tone_curve.rs:1`](../../core/dr-pipeline/tests/tone_curve.rs#L1), [`core/dr-segment/src/refine.rs:937`](../../core/dr-segment/src/refine.rs#L937), [`ui/dr-ui/src/develop/curves.rs:163`](../../ui/dr-ui/src/develop/curves.rs#L163), [`ui/dr-ui/src/develop/framing.rs:10`](../../ui/dr-ui/src/develop/framing.rs#L10), [`ui/dr-ui/src/develop/framing.rs:298`](../../ui/dr-ui/src/develop/framing.rs#L298), [`ui/dr-ui/src/develop/framing.rs:328`](../../ui/dr-ui/src/develop/framing.rs#L328), [`ui/dr-ui/src/develop/framing.rs:394`](../../ui/dr-ui/src/develop/framing.rs#L394), [`ui/dr-ui/src/develop/framing.rs:408`](../../ui/dr-ui/src/develop/framing.rs#L408), [`ui/dr-ui/src/develop/framing.rs:644`](../../ui/dr-ui/src/develop/framing.rs#L644), [`ui/dr-ui/src/develop/framing.rs:71`](../../ui/dr-ui/src/develop/framing.rs#L71), [`ui/dr-ui/src/develop/mask_ops.rs:1076`](../../ui/dr-ui/src/develop/mask_ops.rs#L1076), [`ui/dr-ui/src/develop/mask_ops.rs:1340`](../../ui/dr-ui/src/develop/mask_ops.rs#L1340), [`ui/dr-ui/src/develop/mask_ops.rs:178`](../../ui/dr-ui/src/develop/mask_ops.rs#L178), [`ui/dr-ui/src/develop/mask_ops.rs:969`](../../ui/dr-ui/src/develop/mask_ops.rs#L969), [`ui/dr-ui/src/develop/masks.rs:263`](../../ui/dr-ui/src/develop/masks.rs#L263), [`ui/dr-ui/src/develop/masks.rs:361`](../../ui/dr-ui/src/develop/masks.rs#L361), [`ui/dr-ui/src/develop/masks.rs:743`](../../ui/dr-ui/src/develop/masks.rs#L743), [`ui/dr-ui/src/develop/masks.rs:773`](../../ui/dr-ui/src/develop/masks.rs#L773), [`ui/dr-ui/src/develop/render.rs:1235`](../../ui/dr-ui/src/develop/render.rs#L1235), [`ui/dr-ui/src/develop/rows.rs:106`](../../ui/dr-ui/src/develop/rows.rs#L106), [`ui/dr-ui/src/develop/rows.rs:195`](../../ui/dr-ui/src/develop/rows.rs#L195), [`ui/dr-ui/src/develop/rows.rs:231`](../../ui/dr-ui/src/develop/rows.rs#L231), [`ui/dr-ui/src/develop/rows.rs:679`](../../ui/dr-ui/src/develop/rows.rs#L679), [`ui/dr-ui/src/develop/segmentation.rs:139`](../../ui/dr-ui/src/develop/segmentation.rs#L139), [`ui/dr-ui/src/develop/segmentation.rs:302`](../../ui/dr-ui/src/develop/segmentation.rs#L302), [`ui/dr-ui/src/develop/segmentation.rs:339`](../../ui/dr-ui/src/develop/segmentation.rs#L339), [`ui/dr-ui/src/develop/segmentation.rs:572`](../../ui/dr-ui/src/develop/segmentation.rs#L572), [`ui/dr-ui/src/develop/segmentation.rs:590`](../../ui/dr-ui/src/develop/segmentation.rs#L590), [`ui/dr-ui/src/develop/segmentation.rs:604`](../../ui/dr-ui/src/develop/segmentation.rs#L604), [`ui/dr-ui/src/develop/segmentation.rs:626`](../../ui/dr-ui/src/develop/segmentation.rs#L626), [`ui/dr-ui/src/develop/segmentation.rs:77`](../../ui/dr-ui/src/develop/segmentation.rs#L77), [`ui/dr-ui/src/develop/segmentation.rs:806`](../../ui/dr-ui/src/develop/segmentation.rs#L806), [`ui/dr-ui/src/develop/session.rs:162`](../../ui/dr-ui/src/develop/session.rs#L162), [`ui/dr-ui/src/develop/session.rs:255`](../../ui/dr-ui/src/develop/session.rs#L255), [`ui/dr-ui/src/develop/session.rs:284`](../../ui/dr-ui/src/develop/session.rs#L284), [`ui/dr-ui/src/develop/session.rs:434`](../../ui/dr-ui/src/develop/session.rs#L434), [`ui/dr-ui/src/develop/session.rs:494`](../../ui/dr-ui/src/develop/session.rs#L494), [`ui/dr-ui/src/develop/session.rs:566`](../../ui/dr-ui/src/develop/session.rs#L566), [`ui/dr-ui/src/develop/session.rs:721`](../../ui/dr-ui/src/develop/session.rs#L721), [`ui/dr-ui/src/develop/white_balance.rs:11`](../../ui/dr-ui/src/develop/white_balance.rs#L11), [`ui/dr-ui/src/develop/white_balance.rs:162`](../../ui/dr-ui/src/develop/white_balance.rs#L162), [`ui/dr-ui/src/develop/white_balance.rs:193`](../../ui/dr-ui/src/develop/white_balance.rs#L193), [`ui/dr-ui/src/develop/white_balance.rs:275`](../../ui/dr-ui/src/develop/white_balance.rs#L275), [`ui/dr-ui/src/develop/white_balance.rs:336`](../../ui/dr-ui/src/develop/white_balance.rs#L336), [`ui/dr-ui/src/develop_ui.rs:1113`](../../ui/dr-ui/src/develop_ui.rs#L1113), [`ui/dr-ui/src/develop_ui.rs:117`](../../ui/dr-ui/src/develop_ui.rs#L117), [`ui/dr-ui/src/develop_ui.rs:1210`](../../ui/dr-ui/src/develop_ui.rs#L1210), [`ui/dr-ui/src/develop_ui.rs:1264`](../../ui/dr-ui/src/develop_ui.rs#L1264), [`ui/dr-ui/src/develop_ui.rs:514`](../../ui/dr-ui/src/develop_ui.rs#L514), [`ui/dr-ui/src/develop_ui.rs:734`](../../ui/dr-ui/src/develop_ui.rs#L734), [`ui/dr-ui/src/labels.rs:35`](../../ui/dr-ui/src/labels.rs#L35), [`ui/dr-ui/src/lib.rs:2155`](../../ui/dr-ui/src/lib.rs#L2155), [`ui/dr-ui/src/lib.rs:456`](../../ui/dr-ui/src/lib.rs#L456), [`ui/dr-ui/src/lib.rs:486`](../../ui/dr-ui/src/lib.rs#L486), [`ui/dr-ui/src/lib.rs:594`](../../ui/dr-ui/src/lib.rs#L594), [`ui/dr-ui/src/lib.rs:618`](../../ui/dr-ui/src/lib.rs#L618), [`ui/dr-ui/src/library/sidecar.rs:66`](../../ui/dr-ui/src/library/sidecar.rs#L66), [`ui/dr-ui/src/masks_ui.rs:1608`](../../ui/dr-ui/src/masks_ui.rs#L1608), [`ui/dr-ui/src/masks_ui.rs:1722`](../../ui/dr-ui/src/masks_ui.rs#L1722), [`ui/dr-ui/src/masks_ui.rs:339`](../../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/masks_ui.rs:44`](../../ui/dr-ui/src/masks_ui.rs#L44), [`ui/dr-ui/src/presets.rs:414`](../../ui/dr-ui/src/presets.rs#L414), [`ui/dr-ui/src/segmentation.rs:117`](../../ui/dr-ui/src/segmentation.rs#L117), [`ui/dr-ui/src/segmentation.rs:353`](../../ui/dr-ui/src/segmentation.rs#L353), [`ui/dr-ui/src/segmentation.rs:369`](../../ui/dr-ui/src/segmentation.rs#L369), [`ui/dr-ui/src/segmentation.rs:499`](../../ui/dr-ui/src/segmentation.rs#L499), [`ui/dr-ui/src/segmentation.rs:527`](../../ui/dr-ui/src/segmentation.rs#L527), [`ui/dr-ui/ui/adjust.slint:1050`](../../ui/dr-ui/ui/adjust.slint#L1050), [`ui/dr-ui/ui/adjust.slint:127`](../../ui/dr-ui/ui/adjust.slint#L127), [`ui/dr-ui/ui/adjust.slint:1658`](../../ui/dr-ui/ui/adjust.slint#L1658), [`ui/dr-ui/ui/adjust.slint:173`](../../ui/dr-ui/ui/adjust.slint#L173), [`ui/dr-ui/ui/adjust.slint:47`](../../ui/dr-ui/ui/adjust.slint#L47), [`ui/dr-ui/ui/adjust.slint:626`](../../ui/dr-ui/ui/adjust.slint#L626), [`ui/dr-ui/ui/adjust.slint:662`](../../ui/dr-ui/ui/adjust.slint#L662), [`ui/dr-ui/ui/adjust.slint:681`](../../ui/dr-ui/ui/adjust.slint#L681), [`ui/dr-ui/ui/adjust.slint:874`](../../ui/dr-ui/ui/adjust.slint#L874), [`ui/dr-ui/ui/adjust.slint:973`](../../ui/dr-ui/ui/adjust.slint#L973), [`ui/dr-ui/ui/app.slint:2239`](../../ui/dr-ui/ui/app.slint#L2239), [`ui/dr-ui/ui/app.slint:2301`](../../ui/dr-ui/ui/app.slint#L2301), [`ui/dr-ui/ui/app.slint:242`](../../ui/dr-ui/ui/app.slint#L242), [`ui/dr-ui/ui/develop.slint:375`](../../ui/dr-ui/ui/develop.slint#L375), [`ui/dr-ui/ui/masks.slint:1246`](../../ui/dr-ui/ui/masks.slint#L1246), [`ui/dr-ui/ui/masks.slint:779`](../../ui/dr-ui/ui/masks.slint#L779), [`ui/dr-ui/ui/masks.slint:838`](../../ui/dr-ui/ui/masks.slint#L838) | | FR-DEV-3a | [`core/dr-pipeline/ops/exposure.yaml:1`](../../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/descriptor.rs:212`](../../core/dr-pipeline/src/descriptor.rs#L212), [`core/dr-pipeline/src/descriptor.rs:252`](../../core/dr-pipeline/src/descriptor.rs#L252), [`core/dr-pipeline/src/descriptor.rs:276`](../../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/descriptor.rs:331`](../../core/dr-pipeline/src/descriptor.rs#L331), [`core/dr-pipeline/src/framing.rs:555`](../../core/dr-pipeline/src/framing.rs#L555), [`core/dr-pipeline/src/graph.rs:25`](../../core/dr-pipeline/src/graph.rs#L25), [`core/dr-pipeline/src/graph.rs:393`](../../core/dr-pipeline/src/graph.rs#L393), [`core/dr-pipeline/src/graph.rs:47`](../../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/graph.rs:534`](../../core/dr-pipeline/src/graph.rs#L534), [`core/dr-pipeline/src/graph.rs:60`](../../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/mask.rs:1746`](../../core/dr-pipeline/src/mask.rs#L1746), [`core/dr-pipeline/src/neutral.rs:1`](../../core/dr-pipeline/src/neutral.rs#L1), [`core/dr-pipeline/src/neutral.rs:378`](../../core/dr-pipeline/src/neutral.rs#L378), [`core/dr-pipeline/src/operation.rs:232`](../../core/dr-pipeline/src/operation.rs#L232), [`core/dr-pipeline/src/operation.rs:400`](../../core/dr-pipeline/src/operation.rs#L400), [`core/dr-pipeline/src/ops/curve.rs:319`](../../core/dr-pipeline/src/ops/curve.rs#L319), [`ui/dr-ui/src/develop/curves.rs:36`](../../ui/dr-ui/src/develop/curves.rs#L36), [`ui/dr-ui/src/develop/rows.rs:118`](../../ui/dr-ui/src/develop/rows.rs#L118), [`ui/dr-ui/src/develop/rows.rs:679`](../../ui/dr-ui/src/develop/rows.rs#L679), [`ui/dr-ui/src/develop/rows.rs:877`](../../ui/dr-ui/src/develop/rows.rs#L877), [`ui/dr-ui/src/lib.rs:931`](../../ui/dr-ui/src/lib.rs#L931), [`ui/dr-ui/tests/ui_names_no_operation.rs:1`](../../ui/dr-ui/tests/ui_names_no_operation.rs#L1), [`ui/dr-ui/ui/app.slint:2693`](../../ui/dr-ui/ui/app.slint#L2693) | | FR-DEV-3b | [`core/dr-pipeline/src/descriptor.rs:276`](../../core/dr-pipeline/src/descriptor.rs#L276), [`core/dr-pipeline/src/framing.rs:555`](../../core/dr-pipeline/src/framing.rs#L555), [`core/dr-pipeline/src/graph.rs:60`](../../core/dr-pipeline/src/graph.rs#L60), [`core/dr-pipeline/src/operation.rs:400`](../../core/dr-pipeline/src/operation.rs#L400), [`ui/dr-ui/ui/app.slint:2977`](../../ui/dr-ui/ui/app.slint#L2977) | | FR-DEV-3c | [`core/dr-pipeline/ops/exposure.yaml:1`](../../core/dr-pipeline/ops/exposure.yaml#L1), [`core/dr-pipeline/src/graph.rs:393`](../../core/dr-pipeline/src/graph.rs#L393), [`core/dr-pipeline/src/graph.rs:47`](../../core/dr-pipeline/src/graph.rs#L47), [`core/dr-pipeline/src/mask.rs:1746`](../../core/dr-pipeline/src/mask.rs#L1746), [`core/dr-pipeline/src/preset.rs:927`](../../core/dr-pipeline/src/preset.rs#L927), [`ui/dr-ui/src/develop/rows.rs:928`](../../ui/dr-ui/src/develop/rows.rs#L928) | -| FR-DEV-3d | [`core/dr-gpu/src/adjust.rs:1047`](../../core/dr-gpu/src/adjust.rs#L1047), [`core/dr-gpu/src/adjust.rs:104`](../../core/dr-gpu/src/adjust.rs#L104), [`core/dr-gpu/src/adjust.rs:1271`](../../core/dr-gpu/src/adjust.rs#L1271), [`core/dr-gpu/src/adjust.rs:1365`](../../core/dr-gpu/src/adjust.rs#L1365), [`core/dr-gpu/src/adjust.rs:74`](../../core/dr-gpu/src/adjust.rs#L74), [`core/dr-gpu/tests/capture_sharpen.rs:434`](../../core/dr-gpu/tests/capture_sharpen.rs#L434), [`core/dr-gpu/tests/detail_stage.rs:242`](../../core/dr-gpu/tests/detail_stage.rs#L242), [`core/dr-gpu/tests/local_contrast.rs:558`](../../core/dr-gpu/tests/local_contrast.rs#L558), [`core/dr-gpu/tests/noise_reduction.rs:556`](../../core/dr-gpu/tests/noise_reduction.rs#L556), [`core/dr-pipeline/src/framing.rs:468`](../../core/dr-pipeline/src/framing.rs#L468), [`core/dr-pipeline/src/graph.rs:997`](../../core/dr-pipeline/src/graph.rs#L997), [`core/dr-pipeline/src/operation.rs:32`](../../core/dr-pipeline/src/operation.rs#L32), [`core/dr-pipeline/src/operation.rs:490`](../../core/dr-pipeline/src/operation.rs#L490), [`core/dr-pipeline/src/operation.rs:53`](../../core/dr-pipeline/src/operation.rs#L53), [`core/dr-pipeline/src/operation.rs:71`](../../core/dr-pipeline/src/operation.rs#L71) | -| FR-DEV-3e | [`core/dr-decode/src/lib.rs:125`](../../core/dr-decode/src/lib.rs#L125), [`core/dr-decode/src/lib.rs:752`](../../core/dr-decode/src/lib.rs#L752), [`core/dr-decode/src/lib.rs:792`](../../core/dr-decode/src/lib.rs#L792), [`core/dr-decode/src/profile.rs:104`](../../core/dr-decode/src/profile.rs#L104), [`core/dr-decode/src/profile.rs:153`](../../core/dr-decode/src/profile.rs#L153), [`core/dr-decode/src/profile.rs:1`](../../core/dr-decode/src/profile.rs#L1), [`core/dr-decode/src/profile.rs:237`](../../core/dr-decode/src/profile.rs#L237), [`core/dr-decode/src/profile.rs:288`](../../core/dr-decode/src/profile.rs#L288), [`core/dr-decode/src/profile.rs:345`](../../core/dr-decode/src/profile.rs#L345), [`core/dr-decode/src/profile.rs:475`](../../core/dr-decode/src/profile.rs#L475), [`core/dr-decode/src/profile.rs:509`](../../core/dr-decode/src/profile.rs#L509), [`core/dr-decode/src/profile.rs:680`](../../core/dr-decode/src/profile.rs#L680), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2296`](../../core/dr-pipeline/src/operation.rs#L2296), [`core/dr-pipeline/src/operation.rs:2320`](../../core/dr-pipeline/src/operation.rs#L2320), [`core/dr-pipeline/src/operation.rs:336`](../../core/dr-pipeline/src/operation.rs#L336), [`core/dr-pipeline/src/operation.rs:357`](../../core/dr-pipeline/src/operation.rs#L357), [`core/dr-pipeline/src/operation.rs:431`](../../core/dr-pipeline/src/operation.rs#L431), [`core/dr-pipeline/src/operation.rs:451`](../../core/dr-pipeline/src/operation.rs#L451), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227) | -| FR-DEV-3f | [`core/dr-film/src/bake.rs:161`](../../core/dr-film/src/bake.rs#L161), [`core/dr-film/src/bake.rs:384`](../../core/dr-film/src/bake.rs#L384), [`core/dr-film/src/bake.rs:52`](../../core/dr-film/src/bake.rs#L52), [`core/dr-film/src/bake.rs:662`](../../core/dr-film/src/bake.rs#L662), [`core/dr-film/src/bake.rs:689`](../../core/dr-film/src/bake.rs#L689), [`core/dr-film/src/bake.rs:710`](../../core/dr-film/src/bake.rs#L710), [`core/dr-film/src/bake.rs:747`](../../core/dr-film/src/bake.rs#L747), [`core/dr-film/src/bake.rs:95`](../../core/dr-film/src/bake.rs#L95), [`core/dr-film/src/boolean_grain.rs:1`](../../core/dr-film/src/boolean_grain.rs#L1), [`core/dr-film/src/boolean_grain.rs:78`](../../core/dr-film/src/boolean_grain.rs#L78), [`core/dr-film/src/grain.rs:140`](../../core/dr-film/src/grain.rs#L140), [`core/dr-film/src/grain.rs:1`](../../core/dr-film/src/grain.rs#L1), [`core/dr-film/src/grain.rs:302`](../../core/dr-film/src/grain.rs#L302), [`core/dr-film/src/grain.rs:79`](../../core/dr-film/src/grain.rs#L79), [`core/dr-film/src/lib.rs:160`](../../core/dr-film/src/lib.rs#L160), [`core/dr-film/src/lib.rs:1`](../../core/dr-film/src/lib.rs#L1), [`core/dr-film/src/profile.rs:100`](../../core/dr-film/src/profile.rs#L100), [`core/dr-film/src/profile.rs:142`](../../core/dr-film/src/profile.rs#L142), [`core/dr-film/src/profile.rs:182`](../../core/dr-film/src/profile.rs#L182), [`core/dr-film/src/profile.rs:259`](../../core/dr-film/src/profile.rs#L259), [`core/dr-film/src/profile.rs:502`](../../core/dr-film/src/profile.rs#L502), [`core/dr-film/src/profile.rs:73`](../../core/dr-film/src/profile.rs#L73), [`core/dr-gpu/src/adjust.rs:142`](../../core/dr-gpu/src/adjust.rs#L142), [`core/dr-gpu/src/adjust.rs:412`](../../core/dr-gpu/src/adjust.rs#L412), [`core/dr-gpu/src/adjust.rs:591`](../../core/dr-gpu/src/adjust.rs#L591), [`core/dr-gpu/src/adjust.rs:67`](../../core/dr-gpu/src/adjust.rs#L67), [`core/dr-gpu/src/adjust.rs:721`](../../core/dr-gpu/src/adjust.rs#L721), [`core/dr-gpu/tests/film_sim.rs:1`](../../core/dr-gpu/tests/film_sim.rs#L1), [`core/dr-gpu/tests/film_sim.rs:213`](../../core/dr-gpu/tests/film_sim.rs#L213), [`core/dr-gpu/tests/film_sim.rs:347`](../../core/dr-gpu/tests/film_sim.rs#L347), [`core/dr-gpu/tests/film_sim.rs:386`](../../core/dr-gpu/tests/film_sim.rs#L386), [`core/dr-gpu/tests/film_sim.rs:415`](../../core/dr-gpu/tests/film_sim.rs#L415), [`core/dr-gpu/tests/film_sim.rs:455`](../../core/dr-gpu/tests/film_sim.rs#L455), [`core/dr-pipeline/src/graph.rs:103`](../../core/dr-pipeline/src/graph.rs#L103), [`core/dr-pipeline/src/graph.rs:168`](../../core/dr-pipeline/src/graph.rs#L168), [`core/dr-pipeline/src/graph.rs:566`](../../core/dr-pipeline/src/graph.rs#L566), [`core/dr-pipeline/src/mask.rs:2452`](../../core/dr-pipeline/src/mask.rs#L2452), [`core/dr-pipeline/src/mask.rs:2485`](../../core/dr-pipeline/src/mask.rs#L2485), [`core/dr-pipeline/src/operation.rs:1002`](../../core/dr-pipeline/src/operation.rs#L1002), [`core/dr-pipeline/src/operation.rs:1306`](../../core/dr-pipeline/src/operation.rs#L1306), [`core/dr-pipeline/src/operation.rs:1540`](../../core/dr-pipeline/src/operation.rs#L1540), [`core/dr-pipeline/src/operation.rs:1568`](../../core/dr-pipeline/src/operation.rs#L1568), [`core/dr-pipeline/src/operation.rs:1614`](../../core/dr-pipeline/src/operation.rs#L1614), [`core/dr-pipeline/src/operation.rs:2226`](../../core/dr-pipeline/src/operation.rs#L2226), [`core/dr-pipeline/src/operation.rs:296`](../../core/dr-pipeline/src/operation.rs#L296), [`core/dr-pipeline/src/operation.rs:310`](../../core/dr-pipeline/src/operation.rs#L310), [`core/dr-pipeline/src/operation.rs:321`](../../core/dr-pipeline/src/operation.rs#L321), [`core/dr-pipeline/src/operation.rs:336`](../../core/dr-pipeline/src/operation.rs#L336), [`core/dr-pipeline/src/ops/film_sim.rs:126`](../../core/dr-pipeline/src/ops/film_sim.rs#L126), [`core/dr-pipeline/src/ops/film_sim.rs:131`](../../core/dr-pipeline/src/ops/film_sim.rs#L131), [`core/dr-pipeline/src/ops/film_sim.rs:183`](../../core/dr-pipeline/src/ops/film_sim.rs#L183), [`core/dr-pipeline/src/ops/film_sim.rs:1`](../../core/dr-pipeline/src/ops/film_sim.rs#L1), [`core/dr-pipeline/src/ops/film_sim.rs:230`](../../core/dr-pipeline/src/ops/film_sim.rs#L230), [`core/dr-pipeline/src/ops/film_sim.rs:320`](../../core/dr-pipeline/src/ops/film_sim.rs#L320), [`core/dr-pipeline/src/ops/film_sim.rs:429`](../../core/dr-pipeline/src/ops/film_sim.rs#L429), [`core/dr-pipeline/src/ops/film_sim.rs:45`](../../core/dr-pipeline/src/ops/film_sim.rs#L45), [`core/dr-pipeline/src/ops/film_sim.rs:727`](../../core/dr-pipeline/src/ops/film_sim.rs#L727), [`core/dr-pipeline/src/preset.rs:1293`](../../core/dr-pipeline/src/preset.rs#L1293), [`core/dr-pipeline/src/preset.rs:1303`](../../core/dr-pipeline/src/preset.rs#L1303), [`core/dr-pipeline/src/preset.rs:1312`](../../core/dr-pipeline/src/preset.rs#L1312), [`core/dr-pipeline/src/preset.rs:1328`](../../core/dr-pipeline/src/preset.rs#L1328), [`core/dr-pipeline/src/preset.rs:1340`](../../core/dr-pipeline/src/preset.rs#L1340), [`core/dr-pipeline/src/preset.rs:1356`](../../core/dr-pipeline/src/preset.rs#L1356), [`core/dr-pipeline/src/preset.rs:1529`](../../core/dr-pipeline/src/preset.rs#L1529), [`core/dr-pipeline/src/preset.rs:1544`](../../core/dr-pipeline/src/preset.rs#L1544), [`core/dr-pipeline/src/preset.rs:248`](../../core/dr-pipeline/src/preset.rs#L248), [`core/dr-pipeline/src/preset.rs:689`](../../core/dr-pipeline/src/preset.rs#L689), [`core/dr-pipeline/src/preset.rs:778`](../../core/dr-pipeline/src/preset.rs#L778), [`core/dr-pipeline/src/sidecar.rs:1077`](../../core/dr-pipeline/src/sidecar.rs#L1077), [`core/dr-pipeline/src/sidecar.rs:133`](../../core/dr-pipeline/src/sidecar.rs#L133), [`core/dr-pipeline/src/sidecar.rs:217`](../../core/dr-pipeline/src/sidecar.rs#L217), [`core/dr-pipeline/src/sidecar.rs:2724`](../../core/dr-pipeline/src/sidecar.rs#L2724), [`core/dr-pipeline/src/sidecar.rs:2800`](../../core/dr-pipeline/src/sidecar.rs#L2800), [`core/dr-pipeline/src/sidecar.rs:595`](../../core/dr-pipeline/src/sidecar.rs#L595), [`core/dr-pipeline/src/sidecar.rs:898`](../../core/dr-pipeline/src/sidecar.rs#L898), [`core/dr-pipeline/src/state.rs:100`](../../core/dr-pipeline/src/state.rs#L100), [`core/dr-pipeline/src/state.rs:115`](../../core/dr-pipeline/src/state.rs#L115), [`core/dr-pipeline/src/state.rs:60`](../../core/dr-pipeline/src/state.rs#L60), [`ui/dr-ui/src/develop/render.rs:1256`](../../ui/dr-ui/src/develop/render.rs#L1256), [`ui/dr-ui/src/develop/render.rs:1296`](../../ui/dr-ui/src/develop/render.rs#L1296), [`ui/dr-ui/src/develop/render.rs:1331`](../../ui/dr-ui/src/develop/render.rs#L1331), [`ui/dr-ui/src/develop/render.rs:684`](../../ui/dr-ui/src/develop/render.rs#L684), [`ui/dr-ui/src/develop/render.rs:701`](../../ui/dr-ui/src/develop/render.rs#L701), [`ui/dr-ui/src/develop/render.rs:713`](../../ui/dr-ui/src/develop/render.rs#L713), [`ui/dr-ui/src/develop/render.rs:751`](../../ui/dr-ui/src/develop/render.rs#L751), [`ui/dr-ui/src/develop/render.rs:788`](../../ui/dr-ui/src/develop/render.rs#L788), [`ui/dr-ui/src/develop/render.rs:799`](../../ui/dr-ui/src/develop/render.rs#L799), [`ui/dr-ui/src/develop/render.rs:856`](../../ui/dr-ui/src/develop/render.rs#L856), [`ui/dr-ui/src/develop/render.rs:907`](../../ui/dr-ui/src/develop/render.rs#L907), [`ui/dr-ui/src/develop/render.rs:933`](../../ui/dr-ui/src/develop/render.rs#L933), [`ui/dr-ui/src/develop/session.rs:588`](../../ui/dr-ui/src/develop/session.rs#L588), [`ui/dr-ui/src/develop/session.rs:608`](../../ui/dr-ui/src/develop/session.rs#L608), [`ui/dr-ui/src/develop/tabs.rs:80`](../../ui/dr-ui/src/develop/tabs.rs#L80), [`ui/dr-ui/src/develop_ui.rs:447`](../../ui/dr-ui/src/develop_ui.rs#L447), [`ui/dr-ui/src/lib.rs:857`](../../ui/dr-ui/src/lib.rs#L857), [`ui/dr-ui/src/lib.rs:922`](../../ui/dr-ui/src/lib.rs#L922), [`ui/dr-ui/src/library/sidecar.rs:325`](../../ui/dr-ui/src/library/sidecar.rs#L325), [`ui/dr-ui/src/library/sidecar.rs:50`](../../ui/dr-ui/src/library/sidecar.rs#L50), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:602`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L602), [`ui/dr-ui/src/presets.rs:1586`](../../ui/dr-ui/src/presets.rs#L1586), [`ui/dr-ui/src/presets.rs:422`](../../ui/dr-ui/src/presets.rs#L422), [`ui/dr-ui/tests/film_list_reaches_every_stock.rs:1`](../../ui/dr-ui/tests/film_list_reaches_every_stock.rs#L1), [`ui/dr-ui/ui/adjust.slint:1071`](../../ui/dr-ui/ui/adjust.slint#L1071), [`ui/dr-ui/ui/adjust.slint:1081`](../../ui/dr-ui/ui/adjust.slint#L1081), [`ui/dr-ui/ui/adjust.slint:1298`](../../ui/dr-ui/ui/adjust.slint#L1298) | +| FR-DEV-3d | [`core/dr-gpu/src/adjust.rs:104`](../../core/dr-gpu/src/adjust.rs#L104), [`core/dr-gpu/src/adjust.rs:1050`](../../core/dr-gpu/src/adjust.rs#L1050), [`core/dr-gpu/src/adjust.rs:1356`](../../core/dr-gpu/src/adjust.rs#L1356), [`core/dr-gpu/src/adjust.rs:1450`](../../core/dr-gpu/src/adjust.rs#L1450), [`core/dr-gpu/src/adjust.rs:74`](../../core/dr-gpu/src/adjust.rs#L74), [`core/dr-gpu/tests/capture_sharpen.rs:433`](../../core/dr-gpu/tests/capture_sharpen.rs#L433), [`core/dr-gpu/tests/detail_stage.rs:241`](../../core/dr-gpu/tests/detail_stage.rs#L241), [`core/dr-gpu/tests/local_contrast.rs:557`](../../core/dr-gpu/tests/local_contrast.rs#L557), [`core/dr-gpu/tests/noise_reduction.rs:555`](../../core/dr-gpu/tests/noise_reduction.rs#L555), [`core/dr-pipeline/src/framing.rs:468`](../../core/dr-pipeline/src/framing.rs#L468), [`core/dr-pipeline/src/graph.rs:986`](../../core/dr-pipeline/src/graph.rs#L986), [`core/dr-pipeline/src/operation.rs:32`](../../core/dr-pipeline/src/operation.rs#L32), [`core/dr-pipeline/src/operation.rs:490`](../../core/dr-pipeline/src/operation.rs#L490), [`core/dr-pipeline/src/operation.rs:53`](../../core/dr-pipeline/src/operation.rs#L53), [`core/dr-pipeline/src/operation.rs:71`](../../core/dr-pipeline/src/operation.rs#L71) | +| FR-DEV-3e | [`core/dr-decode/src/lib.rs:125`](../../core/dr-decode/src/lib.rs#L125), [`core/dr-decode/src/lib.rs:752`](../../core/dr-decode/src/lib.rs#L752), [`core/dr-decode/src/lib.rs:792`](../../core/dr-decode/src/lib.rs#L792), [`core/dr-decode/src/profile.rs:104`](../../core/dr-decode/src/profile.rs#L104), [`core/dr-decode/src/profile.rs:153`](../../core/dr-decode/src/profile.rs#L153), [`core/dr-decode/src/profile.rs:1`](../../core/dr-decode/src/profile.rs#L1), [`core/dr-decode/src/profile.rs:237`](../../core/dr-decode/src/profile.rs#L237), [`core/dr-decode/src/profile.rs:288`](../../core/dr-decode/src/profile.rs#L288), [`core/dr-decode/src/profile.rs:345`](../../core/dr-decode/src/profile.rs#L345), [`core/dr-decode/src/profile.rs:475`](../../core/dr-decode/src/profile.rs#L475), [`core/dr-decode/src/profile.rs:509`](../../core/dr-decode/src/profile.rs#L509), [`core/dr-decode/src/profile.rs:680`](../../core/dr-decode/src/profile.rs#L680), [`core/dr-pipeline/src/declared/decl.rs:279`](../../core/dr-pipeline/src/declared/decl.rs#L279), [`core/dr-pipeline/src/operation.rs:2369`](../../core/dr-pipeline/src/operation.rs#L2369), [`core/dr-pipeline/src/operation.rs:2393`](../../core/dr-pipeline/src/operation.rs#L2393), [`core/dr-pipeline/src/operation.rs:336`](../../core/dr-pipeline/src/operation.rs#L336), [`core/dr-pipeline/src/operation.rs:357`](../../core/dr-pipeline/src/operation.rs#L357), [`core/dr-pipeline/src/operation.rs:431`](../../core/dr-pipeline/src/operation.rs#L431), [`core/dr-pipeline/src/operation.rs:451`](../../core/dr-pipeline/src/operation.rs#L451), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227) | +| FR-DEV-3f | [`core/dr-film/src/bake.rs:161`](../../core/dr-film/src/bake.rs#L161), [`core/dr-film/src/bake.rs:384`](../../core/dr-film/src/bake.rs#L384), [`core/dr-film/src/bake.rs:52`](../../core/dr-film/src/bake.rs#L52), [`core/dr-film/src/bake.rs:662`](../../core/dr-film/src/bake.rs#L662), [`core/dr-film/src/bake.rs:689`](../../core/dr-film/src/bake.rs#L689), [`core/dr-film/src/bake.rs:710`](../../core/dr-film/src/bake.rs#L710), [`core/dr-film/src/bake.rs:747`](../../core/dr-film/src/bake.rs#L747), [`core/dr-film/src/bake.rs:95`](../../core/dr-film/src/bake.rs#L95), [`core/dr-film/src/boolean_grain.rs:1`](../../core/dr-film/src/boolean_grain.rs#L1), [`core/dr-film/src/boolean_grain.rs:78`](../../core/dr-film/src/boolean_grain.rs#L78), [`core/dr-film/src/grain.rs:140`](../../core/dr-film/src/grain.rs#L140), [`core/dr-film/src/grain.rs:1`](../../core/dr-film/src/grain.rs#L1), [`core/dr-film/src/grain.rs:302`](../../core/dr-film/src/grain.rs#L302), [`core/dr-film/src/grain.rs:79`](../../core/dr-film/src/grain.rs#L79), [`core/dr-film/src/lib.rs:160`](../../core/dr-film/src/lib.rs#L160), [`core/dr-film/src/lib.rs:1`](../../core/dr-film/src/lib.rs#L1), [`core/dr-film/src/profile.rs:100`](../../core/dr-film/src/profile.rs#L100), [`core/dr-film/src/profile.rs:142`](../../core/dr-film/src/profile.rs#L142), [`core/dr-film/src/profile.rs:182`](../../core/dr-film/src/profile.rs#L182), [`core/dr-film/src/profile.rs:259`](../../core/dr-film/src/profile.rs#L259), [`core/dr-film/src/profile.rs:502`](../../core/dr-film/src/profile.rs#L502), [`core/dr-film/src/profile.rs:73`](../../core/dr-film/src/profile.rs#L73), [`core/dr-gpu/src/adjust.rs:144`](../../core/dr-gpu/src/adjust.rs#L144), [`core/dr-gpu/src/adjust.rs:414`](../../core/dr-gpu/src/adjust.rs#L414), [`core/dr-gpu/src/adjust.rs:593`](../../core/dr-gpu/src/adjust.rs#L593), [`core/dr-gpu/src/adjust.rs:67`](../../core/dr-gpu/src/adjust.rs#L67), [`core/dr-gpu/src/adjust.rs:724`](../../core/dr-gpu/src/adjust.rs#L724), [`core/dr-gpu/tests/film_sim.rs:1`](../../core/dr-gpu/tests/film_sim.rs#L1), [`core/dr-gpu/tests/film_sim.rs:213`](../../core/dr-gpu/tests/film_sim.rs#L213), [`core/dr-gpu/tests/film_sim.rs:347`](../../core/dr-gpu/tests/film_sim.rs#L347), [`core/dr-gpu/tests/film_sim.rs:386`](../../core/dr-gpu/tests/film_sim.rs#L386), [`core/dr-gpu/tests/film_sim.rs:415`](../../core/dr-gpu/tests/film_sim.rs#L415), [`core/dr-gpu/tests/film_sim.rs:455`](../../core/dr-gpu/tests/film_sim.rs#L455), [`core/dr-pipeline/src/graph.rs:103`](../../core/dr-pipeline/src/graph.rs#L103), [`core/dr-pipeline/src/graph.rs:168`](../../core/dr-pipeline/src/graph.rs#L168), [`core/dr-pipeline/src/graph.rs:566`](../../core/dr-pipeline/src/graph.rs#L566), [`core/dr-pipeline/src/mask.rs:2452`](../../core/dr-pipeline/src/mask.rs#L2452), [`core/dr-pipeline/src/mask.rs:2485`](../../core/dr-pipeline/src/mask.rs#L2485), [`core/dr-pipeline/src/operation.rs:1034`](../../core/dr-pipeline/src/operation.rs#L1034), [`core/dr-pipeline/src/operation.rs:1379`](../../core/dr-pipeline/src/operation.rs#L1379), [`core/dr-pipeline/src/operation.rs:1613`](../../core/dr-pipeline/src/operation.rs#L1613), [`core/dr-pipeline/src/operation.rs:1641`](../../core/dr-pipeline/src/operation.rs#L1641), [`core/dr-pipeline/src/operation.rs:1687`](../../core/dr-pipeline/src/operation.rs#L1687), [`core/dr-pipeline/src/operation.rs:2299`](../../core/dr-pipeline/src/operation.rs#L2299), [`core/dr-pipeline/src/operation.rs:296`](../../core/dr-pipeline/src/operation.rs#L296), [`core/dr-pipeline/src/operation.rs:310`](../../core/dr-pipeline/src/operation.rs#L310), [`core/dr-pipeline/src/operation.rs:321`](../../core/dr-pipeline/src/operation.rs#L321), [`core/dr-pipeline/src/operation.rs:336`](../../core/dr-pipeline/src/operation.rs#L336), [`core/dr-pipeline/src/ops/film_sim.rs:126`](../../core/dr-pipeline/src/ops/film_sim.rs#L126), [`core/dr-pipeline/src/ops/film_sim.rs:131`](../../core/dr-pipeline/src/ops/film_sim.rs#L131), [`core/dr-pipeline/src/ops/film_sim.rs:183`](../../core/dr-pipeline/src/ops/film_sim.rs#L183), [`core/dr-pipeline/src/ops/film_sim.rs:1`](../../core/dr-pipeline/src/ops/film_sim.rs#L1), [`core/dr-pipeline/src/ops/film_sim.rs:230`](../../core/dr-pipeline/src/ops/film_sim.rs#L230), [`core/dr-pipeline/src/ops/film_sim.rs:320`](../../core/dr-pipeline/src/ops/film_sim.rs#L320), [`core/dr-pipeline/src/ops/film_sim.rs:429`](../../core/dr-pipeline/src/ops/film_sim.rs#L429), [`core/dr-pipeline/src/ops/film_sim.rs:45`](../../core/dr-pipeline/src/ops/film_sim.rs#L45), [`core/dr-pipeline/src/ops/film_sim.rs:727`](../../core/dr-pipeline/src/ops/film_sim.rs#L727), [`core/dr-pipeline/src/preset.rs:1293`](../../core/dr-pipeline/src/preset.rs#L1293), [`core/dr-pipeline/src/preset.rs:1303`](../../core/dr-pipeline/src/preset.rs#L1303), [`core/dr-pipeline/src/preset.rs:1312`](../../core/dr-pipeline/src/preset.rs#L1312), [`core/dr-pipeline/src/preset.rs:1328`](../../core/dr-pipeline/src/preset.rs#L1328), [`core/dr-pipeline/src/preset.rs:1340`](../../core/dr-pipeline/src/preset.rs#L1340), [`core/dr-pipeline/src/preset.rs:1356`](../../core/dr-pipeline/src/preset.rs#L1356), [`core/dr-pipeline/src/preset.rs:1529`](../../core/dr-pipeline/src/preset.rs#L1529), [`core/dr-pipeline/src/preset.rs:1544`](../../core/dr-pipeline/src/preset.rs#L1544), [`core/dr-pipeline/src/preset.rs:248`](../../core/dr-pipeline/src/preset.rs#L248), [`core/dr-pipeline/src/preset.rs:689`](../../core/dr-pipeline/src/preset.rs#L689), [`core/dr-pipeline/src/preset.rs:778`](../../core/dr-pipeline/src/preset.rs#L778), [`core/dr-pipeline/src/sidecar.rs:1077`](../../core/dr-pipeline/src/sidecar.rs#L1077), [`core/dr-pipeline/src/sidecar.rs:133`](../../core/dr-pipeline/src/sidecar.rs#L133), [`core/dr-pipeline/src/sidecar.rs:217`](../../core/dr-pipeline/src/sidecar.rs#L217), [`core/dr-pipeline/src/sidecar.rs:2724`](../../core/dr-pipeline/src/sidecar.rs#L2724), [`core/dr-pipeline/src/sidecar.rs:2800`](../../core/dr-pipeline/src/sidecar.rs#L2800), [`core/dr-pipeline/src/sidecar.rs:595`](../../core/dr-pipeline/src/sidecar.rs#L595), [`core/dr-pipeline/src/sidecar.rs:898`](../../core/dr-pipeline/src/sidecar.rs#L898), [`core/dr-pipeline/src/state.rs:100`](../../core/dr-pipeline/src/state.rs#L100), [`core/dr-pipeline/src/state.rs:115`](../../core/dr-pipeline/src/state.rs#L115), [`core/dr-pipeline/src/state.rs:60`](../../core/dr-pipeline/src/state.rs#L60), [`ui/dr-ui/src/develop/render.rs:1247`](../../ui/dr-ui/src/develop/render.rs#L1247), [`ui/dr-ui/src/develop/render.rs:1287`](../../ui/dr-ui/src/develop/render.rs#L1287), [`ui/dr-ui/src/develop/render.rs:1322`](../../ui/dr-ui/src/develop/render.rs#L1322), [`ui/dr-ui/src/develop/render.rs:675`](../../ui/dr-ui/src/develop/render.rs#L675), [`ui/dr-ui/src/develop/render.rs:692`](../../ui/dr-ui/src/develop/render.rs#L692), [`ui/dr-ui/src/develop/render.rs:704`](../../ui/dr-ui/src/develop/render.rs#L704), [`ui/dr-ui/src/develop/render.rs:742`](../../ui/dr-ui/src/develop/render.rs#L742), [`ui/dr-ui/src/develop/render.rs:779`](../../ui/dr-ui/src/develop/render.rs#L779), [`ui/dr-ui/src/develop/render.rs:790`](../../ui/dr-ui/src/develop/render.rs#L790), [`ui/dr-ui/src/develop/render.rs:847`](../../ui/dr-ui/src/develop/render.rs#L847), [`ui/dr-ui/src/develop/render.rs:898`](../../ui/dr-ui/src/develop/render.rs#L898), [`ui/dr-ui/src/develop/render.rs:924`](../../ui/dr-ui/src/develop/render.rs#L924), [`ui/dr-ui/src/develop/session.rs:588`](../../ui/dr-ui/src/develop/session.rs#L588), [`ui/dr-ui/src/develop/session.rs:608`](../../ui/dr-ui/src/develop/session.rs#L608), [`ui/dr-ui/src/develop/tabs.rs:80`](../../ui/dr-ui/src/develop/tabs.rs#L80), [`ui/dr-ui/src/develop_ui.rs:447`](../../ui/dr-ui/src/develop_ui.rs#L447), [`ui/dr-ui/src/lib.rs:857`](../../ui/dr-ui/src/lib.rs#L857), [`ui/dr-ui/src/lib.rs:922`](../../ui/dr-ui/src/lib.rs#L922), [`ui/dr-ui/src/library/sidecar.rs:325`](../../ui/dr-ui/src/library/sidecar.rs#L325), [`ui/dr-ui/src/library/sidecar.rs:50`](../../ui/dr-ui/src/library/sidecar.rs#L50), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:602`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L602), [`ui/dr-ui/src/presets.rs:1586`](../../ui/dr-ui/src/presets.rs#L1586), [`ui/dr-ui/src/presets.rs:422`](../../ui/dr-ui/src/presets.rs#L422), [`ui/dr-ui/tests/film_list_reaches_every_stock.rs:1`](../../ui/dr-ui/tests/film_list_reaches_every_stock.rs#L1), [`ui/dr-ui/ui/adjust.slint:1071`](../../ui/dr-ui/ui/adjust.slint#L1071), [`ui/dr-ui/ui/adjust.slint:1081`](../../ui/dr-ui/ui/adjust.slint#L1081), [`ui/dr-ui/ui/adjust.slint:1298`](../../ui/dr-ui/ui/adjust.slint#L1298) | | FR-DEV-3h | [`core/dr-decode/src/lib.rs:435`](../../core/dr-decode/src/lib.rs#L435), [`core/dr-decode/src/preview.rs:29`](../../core/dr-decode/src/preview.rs#L29), [`core/dr-pipeline/src/framing.rs:1477`](../../core/dr-pipeline/src/framing.rs#L1477), [`core/dr-pipeline/src/framing.rs:486`](../../core/dr-pipeline/src/framing.rs#L486), [`core/dr-pipeline/src/framing.rs:704`](../../core/dr-pipeline/src/framing.rs#L704), [`core/dr-types/src/lib.rs:339`](../../core/dr-types/src/lib.rs#L339), [`core/dr-types/src/lib.rs:447`](../../core/dr-types/src/lib.rs#L447), [`core/dr-types/src/lib.rs:459`](../../core/dr-types/src/lib.rs#L459), [`core/dr-types/src/lib.rs:475`](../../core/dr-types/src/lib.rs#L475), [`ui/dr-ui/src/develop/masks.rs:280`](../../ui/dr-ui/src/develop/masks.rs#L280), [`ui/dr-ui/src/develop/segmentation.rs:114`](../../ui/dr-ui/src/develop/segmentation.rs#L114), [`ui/dr-ui/src/segmentation.rs:499`](../../ui/dr-ui/src/segmentation.rs#L499) | | FR-DEV-3i | [`core/dr-pipeline/src/mask.rs:558`](../../core/dr-pipeline/src/mask.rs#L558), [`core/dr-segment/src/lib.rs:1`](../../core/dr-segment/src/lib.rs#L1), [`ui/dr-ui/src/segmentation.rs:1`](../../ui/dr-ui/src/segmentation.rs#L1) | -| FR-DEV-3j | [`core/dr-gpu/src/adjust.rs:3205`](../../core/dr-gpu/src/adjust.rs#L3205), [`core/dr-gpu/tests/view_transform.rs:114`](../../core/dr-gpu/tests/view_transform.rs#L114), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:65`](../../core/dr-gpu/tests/view_transform.rs#L65), [`core/dr-gpu/tests/view_transform.rs:88`](../../core/dr-gpu/tests/view_transform.rs#L88), [`core/dr-pipeline/src/operation.rs:2226`](../../core/dr-pipeline/src/operation.rs#L2226), [`core/dr-pipeline/src/operation.rs:2330`](../../core/dr-pipeline/src/operation.rs#L2330), [`core/dr-pipeline/src/operation.rs:2347`](../../core/dr-pipeline/src/operation.rs#L2347), [`core/dr-pipeline/src/operation.rs:861`](../../core/dr-pipeline/src/operation.rs#L861), [`core/dr-pipeline/src/ops/view_transform.rs:168`](../../core/dr-pipeline/src/ops/view_transform.rs#L168), [`core/dr-pipeline/src/ops/view_transform.rs:1`](../../core/dr-pipeline/src/ops/view_transform.rs#L1), [`core/dr-pipeline/src/view.rs:184`](../../core/dr-pipeline/src/view.rs#L184), [`core/dr-pipeline/src/view.rs:197`](../../core/dr-pipeline/src/view.rs#L197), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227), [`core/dr-pipeline/src/view.rs:241`](../../core/dr-pipeline/src/view.rs#L241), [`core/dr-pipeline/src/view.rs:252`](../../core/dr-pipeline/src/view.rs#L252) | -| FR-DEV-4 | [`core/dr-gpu/src/adjust.rs:1047`](../../core/dr-gpu/src/adjust.rs#L1047), [`core/dr-gpu/src/lib.rs:368`](../../core/dr-gpu/src/lib.rs#L368), [`ui/dr-ui/ui/crop.slint:1`](../../ui/dr-ui/ui/crop.slint#L1) | -| FR-DEV-5 | [`core/dr-pipeline/src/graph.rs:1456`](../../core/dr-pipeline/src/graph.rs#L1456), [`core/dr-pipeline/src/graph.rs:587`](../../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:642`](../../core/dr-pipeline/src/graph.rs#L642), [`core/dr-pipeline/src/history.rs:102`](../../core/dr-pipeline/src/history.rs#L102), [`core/dr-pipeline/src/history.rs:110`](../../core/dr-pipeline/src/history.rs#L110), [`core/dr-pipeline/src/history.rs:127`](../../core/dr-pipeline/src/history.rs#L127), [`core/dr-pipeline/src/history.rs:184`](../../core/dr-pipeline/src/history.rs#L184), [`core/dr-pipeline/src/history.rs:1`](../../core/dr-pipeline/src/history.rs#L1), [`core/dr-pipeline/src/history.rs:214`](../../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:234`](../../core/dr-pipeline/src/history.rs#L234), [`core/dr-pipeline/src/history.rs:293`](../../core/dr-pipeline/src/history.rs#L293), [`core/dr-pipeline/src/history.rs:479`](../../core/dr-pipeline/src/history.rs#L479), [`core/dr-pipeline/src/history.rs:489`](../../core/dr-pipeline/src/history.rs#L489), [`core/dr-pipeline/src/history.rs:499`](../../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../../core/dr-pipeline/src/history.rs#L526), [`core/dr-pipeline/src/history.rs:86`](../../core/dr-pipeline/src/history.rs#L86), [`core/dr-pipeline/src/sidecar.rs:1067`](../../core/dr-pipeline/src/sidecar.rs#L1067), [`core/dr-pipeline/src/sidecar.rs:147`](../../core/dr-pipeline/src/sidecar.rs#L147), [`core/dr-pipeline/src/sidecar.rs:2515`](../../core/dr-pipeline/src/sidecar.rs#L2515), [`core/dr-pipeline/src/sidecar.rs:2551`](../../core/dr-pipeline/src/sidecar.rs#L2551), [`core/dr-pipeline/src/sidecar.rs:2563`](../../core/dr-pipeline/src/sidecar.rs#L2563), [`core/dr-pipeline/src/sidecar.rs:318`](../../core/dr-pipeline/src/sidecar.rs#L318), [`core/dr-pipeline/src/sidecar.rs:713`](../../core/dr-pipeline/src/sidecar.rs#L713), [`core/dr-pipeline/src/sidecar.rs:729`](../../core/dr-pipeline/src/sidecar.rs#L729), [`core/dr-pipeline/src/sidecar.rs:876`](../../core/dr-pipeline/src/sidecar.rs#L876), [`core/dr-pipeline/src/state.rs:1`](../../core/dr-pipeline/src/state.rs#L1), [`core/dr-pipeline/src/state.rs:75`](../../core/dr-pipeline/src/state.rs#L75), [`ui/dr-ui/src/develop/framing.rs:870`](../../ui/dr-ui/src/develop/framing.rs#L870), [`ui/dr-ui/src/develop/history.rs:11`](../../ui/dr-ui/src/develop/history.rs#L11), [`ui/dr-ui/src/develop/history.rs:152`](../../ui/dr-ui/src/develop/history.rs#L152), [`ui/dr-ui/src/develop/history.rs:165`](../../ui/dr-ui/src/develop/history.rs#L165), [`ui/dr-ui/src/develop/history.rs:178`](../../ui/dr-ui/src/develop/history.rs#L178), [`ui/dr-ui/src/develop/history.rs:190`](../../ui/dr-ui/src/develop/history.rs#L190), [`ui/dr-ui/src/develop/history.rs:206`](../../ui/dr-ui/src/develop/history.rs#L206), [`ui/dr-ui/src/develop/history.rs:238`](../../ui/dr-ui/src/develop/history.rs#L238), [`ui/dr-ui/src/develop/history.rs:242`](../../ui/dr-ui/src/develop/history.rs#L242), [`ui/dr-ui/src/develop/history.rs:261`](../../ui/dr-ui/src/develop/history.rs#L261), [`ui/dr-ui/src/develop/history.rs:277`](../../ui/dr-ui/src/develop/history.rs#L277), [`ui/dr-ui/src/develop/history.rs:299`](../../ui/dr-ui/src/develop/history.rs#L299), [`ui/dr-ui/src/develop/history.rs:29`](../../ui/dr-ui/src/develop/history.rs#L29), [`ui/dr-ui/src/develop/history.rs:359`](../../ui/dr-ui/src/develop/history.rs#L359), [`ui/dr-ui/src/develop/history.rs:68`](../../ui/dr-ui/src/develop/history.rs#L68), [`ui/dr-ui/src/develop/history.rs:82`](../../ui/dr-ui/src/develop/history.rs#L82), [`ui/dr-ui/src/develop/history.rs:93`](../../ui/dr-ui/src/develop/history.rs#L93), [`ui/dr-ui/src/develop/render.rs:713`](../../ui/dr-ui/src/develop/render.rs#L713), [`ui/dr-ui/src/develop/render.rs:933`](../../ui/dr-ui/src/develop/render.rs#L933), [`ui/dr-ui/src/develop/render.rs:969`](../../ui/dr-ui/src/develop/render.rs#L969), [`ui/dr-ui/src/develop/session.rs:80`](../../ui/dr-ui/src/develop/session.rs#L80), [`ui/dr-ui/src/develop/session.rs:89`](../../ui/dr-ui/src/develop/session.rs#L89), [`ui/dr-ui/src/develop/white_balance.rs:11`](../../ui/dr-ui/src/develop/white_balance.rs#L11), [`ui/dr-ui/src/develop/white_balance.rs:162`](../../ui/dr-ui/src/develop/white_balance.rs#L162), [`ui/dr-ui/src/develop_ui.rs:765`](../../ui/dr-ui/src/develop_ui.rs#L765), [`ui/dr-ui/src/develop_ui.rs:785`](../../ui/dr-ui/src/develop_ui.rs#L785), [`ui/dr-ui/src/labels.rs:12`](../../ui/dr-ui/src/labels.rs#L12), [`ui/dr-ui/src/labels.rs:292`](../../ui/dr-ui/src/labels.rs#L292), [`ui/dr-ui/src/labels.rs:31`](../../ui/dr-ui/src/labels.rs#L31), [`ui/dr-ui/src/lib.rs:2081`](../../ui/dr-ui/src/lib.rs#L2081), [`ui/dr-ui/src/lib.rs:2086`](../../ui/dr-ui/src/lib.rs#L2086), [`ui/dr-ui/src/lib.rs:2118`](../../ui/dr-ui/src/lib.rs#L2118), [`ui/dr-ui/src/lib.rs:2127`](../../ui/dr-ui/src/lib.rs#L2127), [`ui/dr-ui/src/lib.rs:2144`](../../ui/dr-ui/src/lib.rs#L2144), [`ui/dr-ui/src/library/sidecar.rs:351`](../../ui/dr-ui/src/library/sidecar.rs#L351), [`ui/dr-ui/src/library/sidecar.rs:61`](../../ui/dr-ui/src/library/sidecar.rs#L61), [`ui/dr-ui/src/presets.rs:1770`](../../ui/dr-ui/src/presets.rs#L1770), [`ui/dr-ui/src/presets.rs:373`](../../ui/dr-ui/src/presets.rs#L373), [`ui/dr-ui/src/presets.rs:437`](../../ui/dr-ui/src/presets.rs#L437), [`ui/dr-ui/src/presets.rs:557`](../../ui/dr-ui/src/presets.rs#L557), [`ui/dr-ui/ui/history.slint:192`](../../ui/dr-ui/ui/history.slint#L192), [`ui/dr-ui/ui/history.slint:1`](../../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:219`](../../ui/dr-ui/ui/history.slint#L219), [`ui/dr-ui/ui/history.slint:304`](../../ui/dr-ui/ui/history.slint#L304), [`ui/dr-ui/ui/history.slint:43`](../../ui/dr-ui/ui/history.slint#L43), [`ui/dr-ui/ui/history.slint:53`](../../ui/dr-ui/ui/history.slint#L53) | +| FR-DEV-3j | [`core/dr-gpu/src/adjust.rs:1239`](../../core/dr-gpu/src/adjust.rs#L1239), [`core/dr-gpu/src/adjust.rs:1466`](../../core/dr-gpu/src/adjust.rs#L1466), [`core/dr-gpu/src/adjust.rs:3297`](../../core/dr-gpu/src/adjust.rs#L3297), [`core/dr-gpu/tests/view_transform.rs:114`](../../core/dr-gpu/tests/view_transform.rs#L114), [`core/dr-gpu/tests/view_transform.rs:152`](../../core/dr-gpu/tests/view_transform.rs#L152), [`core/dr-gpu/tests/view_transform.rs:1`](../../core/dr-gpu/tests/view_transform.rs#L1), [`core/dr-gpu/tests/view_transform.rs:65`](../../core/dr-gpu/tests/view_transform.rs#L65), [`core/dr-gpu/tests/view_transform.rs:88`](../../core/dr-gpu/tests/view_transform.rs#L88), [`core/dr-pipeline/src/operation.rs:1357`](../../core/dr-pipeline/src/operation.rs#L1357), [`core/dr-pipeline/src/operation.rs:2299`](../../core/dr-pipeline/src/operation.rs#L2299), [`core/dr-pipeline/src/operation.rs:2403`](../../core/dr-pipeline/src/operation.rs#L2403), [`core/dr-pipeline/src/operation.rs:2420`](../../core/dr-pipeline/src/operation.rs#L2420), [`core/dr-pipeline/src/operation.rs:2590`](../../core/dr-pipeline/src/operation.rs#L2590), [`core/dr-pipeline/src/operation.rs:2628`](../../core/dr-pipeline/src/operation.rs#L2628), [`core/dr-pipeline/src/operation.rs:565`](../../core/dr-pipeline/src/operation.rs#L565), [`core/dr-pipeline/src/operation.rs:836`](../../core/dr-pipeline/src/operation.rs#L836), [`core/dr-pipeline/src/operation.rs:883`](../../core/dr-pipeline/src/operation.rs#L883), [`core/dr-pipeline/src/ops/view_transform.rs:168`](../../core/dr-pipeline/src/ops/view_transform.rs#L168), [`core/dr-pipeline/src/ops/view_transform.rs:1`](../../core/dr-pipeline/src/ops/view_transform.rs#L1), [`core/dr-pipeline/src/view.rs:184`](../../core/dr-pipeline/src/view.rs#L184), [`core/dr-pipeline/src/view.rs:197`](../../core/dr-pipeline/src/view.rs#L197), [`core/dr-pipeline/src/view.rs:1`](../../core/dr-pipeline/src/view.rs#L1), [`core/dr-pipeline/src/view.rs:211`](../../core/dr-pipeline/src/view.rs#L211), [`core/dr-pipeline/src/view.rs:227`](../../core/dr-pipeline/src/view.rs#L227), [`core/dr-pipeline/src/view.rs:241`](../../core/dr-pipeline/src/view.rs#L241), [`core/dr-pipeline/src/view.rs:252`](../../core/dr-pipeline/src/view.rs#L252) | +| FR-DEV-4 | [`core/dr-gpu/src/adjust.rs:1050`](../../core/dr-gpu/src/adjust.rs#L1050), [`core/dr-gpu/src/lib.rs:368`](../../core/dr-gpu/src/lib.rs#L368), [`ui/dr-ui/ui/crop.slint:1`](../../ui/dr-ui/ui/crop.slint#L1) | +| FR-DEV-5 | [`core/dr-pipeline/src/graph.rs:1445`](../../core/dr-pipeline/src/graph.rs#L1445), [`core/dr-pipeline/src/graph.rs:587`](../../core/dr-pipeline/src/graph.rs#L587), [`core/dr-pipeline/src/graph.rs:642`](../../core/dr-pipeline/src/graph.rs#L642), [`core/dr-pipeline/src/history.rs:102`](../../core/dr-pipeline/src/history.rs#L102), [`core/dr-pipeline/src/history.rs:110`](../../core/dr-pipeline/src/history.rs#L110), [`core/dr-pipeline/src/history.rs:127`](../../core/dr-pipeline/src/history.rs#L127), [`core/dr-pipeline/src/history.rs:184`](../../core/dr-pipeline/src/history.rs#L184), [`core/dr-pipeline/src/history.rs:1`](../../core/dr-pipeline/src/history.rs#L1), [`core/dr-pipeline/src/history.rs:214`](../../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:234`](../../core/dr-pipeline/src/history.rs#L234), [`core/dr-pipeline/src/history.rs:293`](../../core/dr-pipeline/src/history.rs#L293), [`core/dr-pipeline/src/history.rs:479`](../../core/dr-pipeline/src/history.rs#L479), [`core/dr-pipeline/src/history.rs:489`](../../core/dr-pipeline/src/history.rs#L489), [`core/dr-pipeline/src/history.rs:499`](../../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../../core/dr-pipeline/src/history.rs#L526), [`core/dr-pipeline/src/history.rs:86`](../../core/dr-pipeline/src/history.rs#L86), [`core/dr-pipeline/src/sidecar.rs:1067`](../../core/dr-pipeline/src/sidecar.rs#L1067), [`core/dr-pipeline/src/sidecar.rs:147`](../../core/dr-pipeline/src/sidecar.rs#L147), [`core/dr-pipeline/src/sidecar.rs:2515`](../../core/dr-pipeline/src/sidecar.rs#L2515), [`core/dr-pipeline/src/sidecar.rs:2551`](../../core/dr-pipeline/src/sidecar.rs#L2551), [`core/dr-pipeline/src/sidecar.rs:2563`](../../core/dr-pipeline/src/sidecar.rs#L2563), [`core/dr-pipeline/src/sidecar.rs:318`](../../core/dr-pipeline/src/sidecar.rs#L318), [`core/dr-pipeline/src/sidecar.rs:713`](../../core/dr-pipeline/src/sidecar.rs#L713), [`core/dr-pipeline/src/sidecar.rs:729`](../../core/dr-pipeline/src/sidecar.rs#L729), [`core/dr-pipeline/src/sidecar.rs:876`](../../core/dr-pipeline/src/sidecar.rs#L876), [`core/dr-pipeline/src/state.rs:1`](../../core/dr-pipeline/src/state.rs#L1), [`core/dr-pipeline/src/state.rs:75`](../../core/dr-pipeline/src/state.rs#L75), [`ui/dr-ui/src/develop/framing.rs:870`](../../ui/dr-ui/src/develop/framing.rs#L870), [`ui/dr-ui/src/develop/history.rs:11`](../../ui/dr-ui/src/develop/history.rs#L11), [`ui/dr-ui/src/develop/history.rs:152`](../../ui/dr-ui/src/develop/history.rs#L152), [`ui/dr-ui/src/develop/history.rs:165`](../../ui/dr-ui/src/develop/history.rs#L165), [`ui/dr-ui/src/develop/history.rs:178`](../../ui/dr-ui/src/develop/history.rs#L178), [`ui/dr-ui/src/develop/history.rs:190`](../../ui/dr-ui/src/develop/history.rs#L190), [`ui/dr-ui/src/develop/history.rs:206`](../../ui/dr-ui/src/develop/history.rs#L206), [`ui/dr-ui/src/develop/history.rs:238`](../../ui/dr-ui/src/develop/history.rs#L238), [`ui/dr-ui/src/develop/history.rs:242`](../../ui/dr-ui/src/develop/history.rs#L242), [`ui/dr-ui/src/develop/history.rs:261`](../../ui/dr-ui/src/develop/history.rs#L261), [`ui/dr-ui/src/develop/history.rs:277`](../../ui/dr-ui/src/develop/history.rs#L277), [`ui/dr-ui/src/develop/history.rs:299`](../../ui/dr-ui/src/develop/history.rs#L299), [`ui/dr-ui/src/develop/history.rs:29`](../../ui/dr-ui/src/develop/history.rs#L29), [`ui/dr-ui/src/develop/history.rs:359`](../../ui/dr-ui/src/develop/history.rs#L359), [`ui/dr-ui/src/develop/history.rs:68`](../../ui/dr-ui/src/develop/history.rs#L68), [`ui/dr-ui/src/develop/history.rs:82`](../../ui/dr-ui/src/develop/history.rs#L82), [`ui/dr-ui/src/develop/history.rs:93`](../../ui/dr-ui/src/develop/history.rs#L93), [`ui/dr-ui/src/develop/render.rs:704`](../../ui/dr-ui/src/develop/render.rs#L704), [`ui/dr-ui/src/develop/render.rs:924`](../../ui/dr-ui/src/develop/render.rs#L924), [`ui/dr-ui/src/develop/render.rs:960`](../../ui/dr-ui/src/develop/render.rs#L960), [`ui/dr-ui/src/develop/session.rs:80`](../../ui/dr-ui/src/develop/session.rs#L80), [`ui/dr-ui/src/develop/session.rs:89`](../../ui/dr-ui/src/develop/session.rs#L89), [`ui/dr-ui/src/develop/white_balance.rs:11`](../../ui/dr-ui/src/develop/white_balance.rs#L11), [`ui/dr-ui/src/develop/white_balance.rs:162`](../../ui/dr-ui/src/develop/white_balance.rs#L162), [`ui/dr-ui/src/develop_ui.rs:765`](../../ui/dr-ui/src/develop_ui.rs#L765), [`ui/dr-ui/src/develop_ui.rs:785`](../../ui/dr-ui/src/develop_ui.rs#L785), [`ui/dr-ui/src/labels.rs:12`](../../ui/dr-ui/src/labels.rs#L12), [`ui/dr-ui/src/labels.rs:292`](../../ui/dr-ui/src/labels.rs#L292), [`ui/dr-ui/src/labels.rs:31`](../../ui/dr-ui/src/labels.rs#L31), [`ui/dr-ui/src/lib.rs:2081`](../../ui/dr-ui/src/lib.rs#L2081), [`ui/dr-ui/src/lib.rs:2086`](../../ui/dr-ui/src/lib.rs#L2086), [`ui/dr-ui/src/lib.rs:2118`](../../ui/dr-ui/src/lib.rs#L2118), [`ui/dr-ui/src/lib.rs:2127`](../../ui/dr-ui/src/lib.rs#L2127), [`ui/dr-ui/src/lib.rs:2144`](../../ui/dr-ui/src/lib.rs#L2144), [`ui/dr-ui/src/library/sidecar.rs:351`](../../ui/dr-ui/src/library/sidecar.rs#L351), [`ui/dr-ui/src/library/sidecar.rs:61`](../../ui/dr-ui/src/library/sidecar.rs#L61), [`ui/dr-ui/src/presets.rs:1770`](../../ui/dr-ui/src/presets.rs#L1770), [`ui/dr-ui/src/presets.rs:373`](../../ui/dr-ui/src/presets.rs#L373), [`ui/dr-ui/src/presets.rs:437`](../../ui/dr-ui/src/presets.rs#L437), [`ui/dr-ui/src/presets.rs:557`](../../ui/dr-ui/src/presets.rs#L557), [`ui/dr-ui/ui/history.slint:192`](../../ui/dr-ui/ui/history.slint#L192), [`ui/dr-ui/ui/history.slint:1`](../../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:219`](../../ui/dr-ui/ui/history.slint#L219), [`ui/dr-ui/ui/history.slint:304`](../../ui/dr-ui/ui/history.slint#L304), [`ui/dr-ui/ui/history.slint:43`](../../ui/dr-ui/ui/history.slint#L43), [`ui/dr-ui/ui/history.slint:53`](../../ui/dr-ui/ui/history.slint#L53) | | FR-DEV-6 | [`core/dr-pipeline/src/bundled.rs:1`](../../core/dr-pipeline/src/bundled.rs#L1), [`core/dr-pipeline/src/preset.rs:1293`](../../core/dr-pipeline/src/preset.rs#L1293), [`core/dr-pipeline/src/preset.rs:1303`](../../core/dr-pipeline/src/preset.rs#L1303), [`core/dr-pipeline/src/preset.rs:1312`](../../core/dr-pipeline/src/preset.rs#L1312), [`core/dr-pipeline/src/preset.rs:1328`](../../core/dr-pipeline/src/preset.rs#L1328), [`core/dr-pipeline/src/preset.rs:1340`](../../core/dr-pipeline/src/preset.rs#L1340), [`core/dr-pipeline/src/preset.rs:1356`](../../core/dr-pipeline/src/preset.rs#L1356), [`core/dr-pipeline/src/preset.rs:1382`](../../core/dr-pipeline/src/preset.rs#L1382), [`core/dr-pipeline/src/preset.rs:1404`](../../core/dr-pipeline/src/preset.rs#L1404), [`core/dr-pipeline/src/preset.rs:1418`](../../core/dr-pipeline/src/preset.rs#L1418), [`core/dr-pipeline/src/preset.rs:1436`](../../core/dr-pipeline/src/preset.rs#L1436), [`core/dr-pipeline/src/preset.rs:1529`](../../core/dr-pipeline/src/preset.rs#L1529), [`core/dr-pipeline/src/preset.rs:1544`](../../core/dr-pipeline/src/preset.rs#L1544), [`core/dr-pipeline/src/preset.rs:1`](../../core/dr-pipeline/src/preset.rs#L1), [`core/dr-pipeline/src/preset.rs:501`](../../core/dr-pipeline/src/preset.rs#L501), [`core/dr-pipeline/src/preset.rs:534`](../../core/dr-pipeline/src/preset.rs#L534), [`core/dr-preset-xmp/src/lib.rs:1`](../../core/dr-preset-xmp/src/lib.rs#L1), [`core/dr-preset-xmp/src/lib.rs:492`](../../core/dr-preset-xmp/src/lib.rs#L492), [`core/dr-types/src/settings.rs:443`](../../core/dr-types/src/settings.rs#L443), [`ui/dr-ui/src/develop/session.rs:560`](../../ui/dr-ui/src/develop/session.rs#L560), [`ui/dr-ui/src/develop/session.rs:581`](../../ui/dr-ui/src/develop/session.rs#L581), [`ui/dr-ui/src/develop_ui.rs:167`](../../ui/dr-ui/src/develop_ui.rs#L167), [`ui/dr-ui/src/develop_ui.rs:196`](../../ui/dr-ui/src/develop_ui.rs#L196), [`ui/dr-ui/src/lib.rs:1262`](../../ui/dr-ui/src/lib.rs#L1262), [`ui/dr-ui/src/library/sidecar.rs:12`](../../ui/dr-ui/src/library/sidecar.rs#L12), [`ui/dr-ui/src/library/sidecar.rs:40`](../../ui/dr-ui/src/library/sidecar.rs#L40), [`ui/dr-ui/src/library/thumbnails_fetch.rs:414`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L414), [`ui/dr-ui/src/library_ui/controller.rs:677`](../../ui/dr-ui/src/library_ui/controller.rs#L677), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:495`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L495), [`ui/dr-ui/src/library_ui/window.rs:678`](../../ui/dr-ui/src/library_ui/window.rs#L678), [`ui/dr-ui/src/preset_store.rs:1`](../../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/presets.rs:1586`](../../ui/dr-ui/src/presets.rs#L1586), [`ui/dr-ui/src/presets.rs:1`](../../ui/dr-ui/src/presets.rs#L1), [`ui/dr-ui/src/presets.rs:707`](../../ui/dr-ui/src/presets.rs#L707), [`ui/dr-ui/src/presets.rs:741`](../../ui/dr-ui/src/presets.rs#L741), [`ui/dr-ui/ui/adjust.slint:937`](../../ui/dr-ui/ui/adjust.slint#L937), [`ui/dr-ui/ui/adjust.slint:962`](../../ui/dr-ui/ui/adjust.slint#L962), [`ui/dr-ui/ui/app.slint:1090`](../../ui/dr-ui/ui/app.slint#L1090), [`ui/dr-ui/ui/app.slint:1511`](../../ui/dr-ui/ui/app.slint#L1511), [`ui/dr-ui/ui/app.slint:1791`](../../ui/dr-ui/ui/app.slint#L1791), [`ui/dr-ui/ui/app.slint:2495`](../../ui/dr-ui/ui/app.slint#L2495), [`ui/dr-ui/ui/app.slint:3433`](../../ui/dr-ui/ui/app.slint#L3433), [`ui/dr-ui/ui/app.slint:3478`](../../ui/dr-ui/ui/app.slint#L3478), [`ui/dr-ui/ui/app.slint:525`](../../ui/dr-ui/ui/app.slint#L525), [`ui/dr-ui/ui/app.slint:536`](../../ui/dr-ui/ui/app.slint#L536), [`ui/dr-ui/ui/app.slint:694`](../../ui/dr-ui/ui/app.slint#L694), [`ui/dr-ui/ui/develop.slint:257`](../../ui/dr-ui/ui/develop.slint#L257), [`ui/dr-ui/ui/icons.slint:390`](../../ui/dr-ui/ui/icons.slint#L390), [`ui/dr-ui/ui/library.slint:2000`](../../ui/dr-ui/ui/library.slint#L2000), [`ui/dr-ui/ui/library.slint:2006`](../../ui/dr-ui/ui/library.slint#L2006), [`ui/dr-ui/ui/library.slint:3196`](../../ui/dr-ui/ui/library.slint#L3196), [`ui/dr-ui/ui/library.slint:5132`](../../ui/dr-ui/ui/library.slint#L5132), [`ui/dr-ui/ui/library.slint:5150`](../../ui/dr-ui/ui/library.slint#L5150), [`ui/dr-ui/ui/presets.slint:132`](../../ui/dr-ui/ui/presets.slint#L132), [`ui/dr-ui/ui/presets.slint:140`](../../ui/dr-ui/ui/presets.slint#L140), [`ui/dr-ui/ui/presets.slint:20`](../../ui/dr-ui/ui/presets.slint#L20), [`ui/dr-ui/ui/presets.slint:310`](../../ui/dr-ui/ui/presets.slint#L310), [`ui/dr-ui/ui/presets.slint:32`](../../ui/dr-ui/ui/presets.slint#L32), [`ui/dr-ui/ui/presets.slint:348`](../../ui/dr-ui/ui/presets.slint#L348), [`ui/dr-ui/ui/presets.slint:383`](../../ui/dr-ui/ui/presets.slint#L383), [`ui/dr-ui/ui/presets.slint:45`](../../ui/dr-ui/ui/presets.slint#L45), [`ui/dr-ui/ui/presets.slint:6`](../../ui/dr-ui/ui/presets.slint#L6), [`ui/dr-ui/ui/presets.slint:86`](../../ui/dr-ui/ui/presets.slint#L86), [`ui/dr-ui/ui/settings.slint:126`](../../ui/dr-ui/ui/settings.slint#L126), [`ui/dr-ui/ui/settings.slint:690`](../../ui/dr-ui/ui/settings.slint#L690), [`ui/dr-ui/ui/toolrail.slint:122`](../../ui/dr-ui/ui/toolrail.slint#L122), [`ui/dr-ui/ui/toolrail.slint:441`](../../ui/dr-ui/ui/toolrail.slint#L441) | -| FR-DEV-7 | [`core/dr-pipeline/src/history.rs:214`](../../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:499`](../../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../../core/dr-pipeline/src/history.rs#L526), [`ui/dr-ui/src/develop/history.rs:107`](../../ui/dr-ui/src/develop/history.rs#L107), [`ui/dr-ui/src/develop/history.rs:124`](../../ui/dr-ui/src/develop/history.rs#L124), [`ui/dr-ui/src/develop/history.rs:206`](../../ui/dr-ui/src/develop/history.rs#L206), [`ui/dr-ui/src/develop/history.rs:238`](../../ui/dr-ui/src/develop/history.rs#L238), [`ui/dr-ui/src/develop/history.rs:359`](../../ui/dr-ui/src/develop/history.rs#L359), [`ui/dr-ui/src/develop/render.rs:493`](../../ui/dr-ui/src/develop/render.rs#L493), [`ui/dr-ui/src/develop/render.rs:534`](../../ui/dr-ui/src/develop/render.rs#L534), [`ui/dr-ui/src/develop/render.rs:969`](../../ui/dr-ui/src/develop/render.rs#L969), [`ui/dr-ui/src/develop/session.rs:105`](../../ui/dr-ui/src/develop/session.rs#L105), [`ui/dr-ui/src/develop_ui.rs:706`](../../ui/dr-ui/src/develop_ui.rs#L706), [`ui/dr-ui/src/develop_ui.rs:765`](../../ui/dr-ui/src/develop_ui.rs#L765), [`ui/dr-ui/src/develop_ui.rs:837`](../../ui/dr-ui/src/develop_ui.rs#L837), [`ui/dr-ui/src/lib.rs:2127`](../../ui/dr-ui/src/lib.rs#L2127), [`ui/dr-ui/src/lib.rs:2204`](../../ui/dr-ui/src/lib.rs#L2204), [`ui/dr-ui/src/lib.rs:2218`](../../ui/dr-ui/src/lib.rs#L2218), [`ui/dr-ui/src/lib.rs:448`](../../ui/dr-ui/src/lib.rs#L448), [`ui/dr-ui/ui/app.slint:224`](../../ui/dr-ui/ui/app.slint#L224), [`ui/dr-ui/ui/app.slint:2362`](../../ui/dr-ui/ui/app.slint#L2362), [`ui/dr-ui/ui/app.slint:2408`](../../ui/dr-ui/ui/app.slint#L2408), [`ui/dr-ui/ui/app.slint:2977`](../../ui/dr-ui/ui/app.slint#L2977), [`ui/dr-ui/ui/history.slint:103`](../../ui/dr-ui/ui/history.slint#L103), [`ui/dr-ui/ui/history.slint:1`](../../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:227`](../../ui/dr-ui/ui/history.slint#L227), [`ui/dr-ui/ui/history.slint:53`](../../ui/dr-ui/ui/history.slint#L53), [`ui/dr-ui/ui/widgets.slint:72`](../../ui/dr-ui/ui/widgets.slint#L72) | -| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:405`](../../core/dr-gpu/src/detail.rs#L405), [`core/dr-gpu/src/detail.rs:623`](../../core/dr-gpu/src/detail.rs#L623), [`core/dr-gpu/tests/detail_instances.rs:1`](../../core/dr-gpu/tests/detail_instances.rs#L1), [`core/dr-gpu/tests/spot_removal.rs:1`](../../core/dr-gpu/tests/spot_removal.rs#L1), [`core/dr-pipeline/src/detail.rs:410`](../../core/dr-pipeline/src/detail.rs#L410), [`core/dr-pipeline/src/detail.rs:452`](../../core/dr-pipeline/src/detail.rs#L452), [`core/dr-pipeline/src/detail.rs:487`](../../core/dr-pipeline/src/detail.rs#L487), [`core/dr-pipeline/src/detail.rs:573`](../../core/dr-pipeline/src/detail.rs#L573), [`core/dr-pipeline/src/graph.rs:1098`](../../core/dr-pipeline/src/graph.rs#L1098), [`core/dr-pipeline/src/graph.rs:115`](../../core/dr-pipeline/src/graph.rs#L115), [`core/dr-pipeline/src/graph.rs:247`](../../core/dr-pipeline/src/graph.rs#L247), [`core/dr-pipeline/src/operation.rs:365`](../../core/dr-pipeline/src/operation.rs#L365), [`core/dr-pipeline/src/operation.rs:812`](../../core/dr-pipeline/src/operation.rs#L812), [`core/dr-pipeline/src/sidecar.rs:1104`](../../core/dr-pipeline/src/sidecar.rs#L1104), [`core/dr-pipeline/src/sidecar.rs:1158`](../../core/dr-pipeline/src/sidecar.rs#L1158), [`core/dr-pipeline/src/sidecar.rs:1188`](../../core/dr-pipeline/src/sidecar.rs#L1188), [`core/dr-pipeline/src/sidecar.rs:233`](../../core/dr-pipeline/src/sidecar.rs#L233), [`core/dr-pipeline/src/sidecar.rs:410`](../../core/dr-pipeline/src/sidecar.rs#L410), [`core/dr-pipeline/src/sidecar.rs:910`](../../core/dr-pipeline/src/sidecar.rs#L910), [`core/dr-pipeline/src/spot.rs:115`](../../core/dr-pipeline/src/spot.rs#L115), [`core/dr-pipeline/src/spot.rs:151`](../../core/dr-pipeline/src/spot.rs#L151), [`core/dr-pipeline/src/spot.rs:1`](../../core/dr-pipeline/src/spot.rs#L1), [`core/dr-pipeline/src/spot.rs:207`](../../core/dr-pipeline/src/spot.rs#L207), [`core/dr-pipeline/src/spot.rs:387`](../../core/dr-pipeline/src/spot.rs#L387), [`core/dr-pipeline/src/spot.rs:472`](../../core/dr-pipeline/src/spot.rs#L472), [`core/dr-pipeline/src/spot.rs:582`](../../core/dr-pipeline/src/spot.rs#L582), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`core/dr-pipeline/src/state.rs:103`](../../core/dr-pipeline/src/state.rs#L103), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-pipeline/tests/spots.rs:1`](../../core/dr-pipeline/tests/spots.rs#L1), [`ui/dr-ui/src/develop/repairs.rs:114`](../../ui/dr-ui/src/develop/repairs.rs#L114), [`ui/dr-ui/src/develop/repairs.rs:11`](../../ui/dr-ui/src/develop/repairs.rs#L11), [`ui/dr-ui/src/develop/repairs.rs:197`](../../ui/dr-ui/src/develop/repairs.rs#L197), [`ui/dr-ui/src/develop/repairs.rs:211`](../../ui/dr-ui/src/develop/repairs.rs#L211), [`ui/dr-ui/src/develop/repairs.rs:49`](../../ui/dr-ui/src/develop/repairs.rs#L49), [`ui/dr-ui/src/develop/session.rs:216`](../../ui/dr-ui/src/develop/session.rs#L216), [`ui/dr-ui/src/develop_ui.rs:992`](../../ui/dr-ui/src/develop_ui.rs#L992), [`ui/dr-ui/src/labels.rs:80`](../../ui/dr-ui/src/labels.rs#L80), [`ui/dr-ui/src/lib.rs:2162`](../../ui/dr-ui/src/lib.rs#L2162), [`ui/dr-ui/src/lib.rs:491`](../../ui/dr-ui/src/lib.rs#L491), [`ui/dr-ui/src/spots_ui.rs:19`](../../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/src/spots_ui.rs:1`](../../ui/dr-ui/src/spots_ui.rs#L1), [`ui/dr-ui/src/spots_ui.rs:265`](../../ui/dr-ui/src/spots_ui.rs#L265), [`ui/dr-ui/ui/app.slint:2215`](../../ui/dr-ui/ui/app.slint#L2215), [`ui/dr-ui/ui/app.slint:2458`](../../ui/dr-ui/ui/app.slint#L2458), [`ui/dr-ui/ui/app.slint:3326`](../../ui/dr-ui/ui/app.slint#L3326), [`ui/dr-ui/ui/icons.slint:378`](../../ui/dr-ui/ui/icons.slint#L378), [`ui/dr-ui/ui/session.slint:102`](../../ui/dr-ui/ui/session.slint#L102), [`ui/dr-ui/ui/session.slint:52`](../../ui/dr-ui/ui/session.slint#L52), [`ui/dr-ui/ui/spots.slint:191`](../../ui/dr-ui/ui/spots.slint#L191), [`ui/dr-ui/ui/spots.slint:49`](../../ui/dr-ui/ui/spots.slint#L49), [`ui/dr-ui/ui/spots.slint:6`](../../ui/dr-ui/ui/spots.slint#L6), [`ui/dr-ui/ui/spots.slint:91`](../../ui/dr-ui/ui/spots.slint#L91) | -| FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:1047`](../../core/dr-gpu/src/adjust.rs#L1047), [`core/dr-gpu/src/adjust.rs:2692`](../../core/dr-gpu/src/adjust.rs#L2692), [`core/dr-gpu/src/adjust.rs:2769`](../../core/dr-gpu/src/adjust.rs#L2769), [`core/dr-gpu/src/adjust.rs:2854`](../../core/dr-gpu/src/adjust.rs#L2854), [`core/dr-gpu/src/adjust.rs:44`](../../core/dr-gpu/src/adjust.rs#L44), [`core/dr-gpu/src/lib.rs:174`](../../core/dr-gpu/src/lib.rs#L174), [`core/dr-gpu/src/lib.rs:194`](../../core/dr-gpu/src/lib.rs#L194), [`core/dr-gpu/src/lib.rs:72`](../../core/dr-gpu/src/lib.rs#L72), [`core/dr-gpu/src/lib.rs:95`](../../core/dr-gpu/src/lib.rs#L95), [`core/dr-gpu/tests/capture_sharpen.rs:200`](../../core/dr-gpu/tests/capture_sharpen.rs#L200), [`core/dr-gpu/tests/detail_stage.rs:328`](../../core/dr-gpu/tests/detail_stage.rs#L328), [`core/dr-gpu/tests/local_contrast.rs:264`](../../core/dr-gpu/tests/local_contrast.rs#L264), [`core/dr-gpu/tests/noise_reduction.rs:378`](../../core/dr-gpu/tests/noise_reduction.rs#L378), [`core/dr-pipeline/src/detail.rs:136`](../../core/dr-pipeline/src/detail.rs#L136), [`core/dr-pipeline/src/detail.rs:542`](../../core/dr-pipeline/src/detail.rs#L542), [`core/dr-pipeline/src/graph.rs:928`](../../core/dr-pipeline/src/graph.rs#L928), [`core/dr-pipeline/src/graph.rs:958`](../../core/dr-pipeline/src/graph.rs#L958), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:659`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L659), [`core/dr-pipeline/src/ops/dehaze.rs:1`](../../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:565`](../../core/dr-pipeline/src/ops/dehaze.rs#L565), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/local_contrast.rs:971`](../../core/dr-pipeline/src/ops/local_contrast.rs#L971), [`core/dr-pipeline/src/ops/noise_reduction.rs:700`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L700), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`ui/dr-ui/src/develop/framing.rs:594`](../../ui/dr-ui/src/develop/framing.rs#L594), [`ui/dr-ui/src/develop/mod.rs:55`](../../ui/dr-ui/src/develop/mod.rs#L55), [`ui/dr-ui/src/develop/render.rs:1026`](../../ui/dr-ui/src/develop/render.rs#L1026), [`ui/dr-ui/src/develop/render.rs:1060`](../../ui/dr-ui/src/develop/render.rs#L1060), [`ui/dr-ui/src/develop/render.rs:1198`](../../ui/dr-ui/src/develop/render.rs#L1198), [`ui/dr-ui/src/develop/render.rs:217`](../../ui/dr-ui/src/develop/render.rs#L217), [`ui/dr-ui/src/develop/render.rs:79`](../../ui/dr-ui/src/develop/render.rs#L79), [`ui/dr-ui/src/lib.rs:1078`](../../ui/dr-ui/src/lib.rs#L1078), [`ui/dr-ui/src/lib.rs:116`](../../ui/dr-ui/src/lib.rs#L116) | -| FR-DSP-3 | [`core/dr-gpu/tests/frame_budget.rs:101`](../../core/dr-gpu/tests/frame_budget.rs#L101), [`core/dr-gpu/tests/local_contrast.rs:329`](../../core/dr-gpu/tests/local_contrast.rs#L329), [`core/dr-pipeline/src/ops/local_contrast.rs:447`](../../core/dr-pipeline/src/ops/local_contrast.rs#L447) | +| FR-DEV-7 | [`core/dr-pipeline/src/history.rs:214`](../../core/dr-pipeline/src/history.rs#L214), [`core/dr-pipeline/src/history.rs:499`](../../core/dr-pipeline/src/history.rs#L499), [`core/dr-pipeline/src/history.rs:526`](../../core/dr-pipeline/src/history.rs#L526), [`ui/dr-ui/src/develop/history.rs:107`](../../ui/dr-ui/src/develop/history.rs#L107), [`ui/dr-ui/src/develop/history.rs:124`](../../ui/dr-ui/src/develop/history.rs#L124), [`ui/dr-ui/src/develop/history.rs:206`](../../ui/dr-ui/src/develop/history.rs#L206), [`ui/dr-ui/src/develop/history.rs:238`](../../ui/dr-ui/src/develop/history.rs#L238), [`ui/dr-ui/src/develop/history.rs:359`](../../ui/dr-ui/src/develop/history.rs#L359), [`ui/dr-ui/src/develop/render.rs:484`](../../ui/dr-ui/src/develop/render.rs#L484), [`ui/dr-ui/src/develop/render.rs:525`](../../ui/dr-ui/src/develop/render.rs#L525), [`ui/dr-ui/src/develop/render.rs:960`](../../ui/dr-ui/src/develop/render.rs#L960), [`ui/dr-ui/src/develop/session.rs:105`](../../ui/dr-ui/src/develop/session.rs#L105), [`ui/dr-ui/src/develop_ui.rs:706`](../../ui/dr-ui/src/develop_ui.rs#L706), [`ui/dr-ui/src/develop_ui.rs:765`](../../ui/dr-ui/src/develop_ui.rs#L765), [`ui/dr-ui/src/develop_ui.rs:837`](../../ui/dr-ui/src/develop_ui.rs#L837), [`ui/dr-ui/src/lib.rs:2127`](../../ui/dr-ui/src/lib.rs#L2127), [`ui/dr-ui/src/lib.rs:2204`](../../ui/dr-ui/src/lib.rs#L2204), [`ui/dr-ui/src/lib.rs:2218`](../../ui/dr-ui/src/lib.rs#L2218), [`ui/dr-ui/src/lib.rs:448`](../../ui/dr-ui/src/lib.rs#L448), [`ui/dr-ui/ui/app.slint:224`](../../ui/dr-ui/ui/app.slint#L224), [`ui/dr-ui/ui/app.slint:2362`](../../ui/dr-ui/ui/app.slint#L2362), [`ui/dr-ui/ui/app.slint:2408`](../../ui/dr-ui/ui/app.slint#L2408), [`ui/dr-ui/ui/app.slint:2977`](../../ui/dr-ui/ui/app.slint#L2977), [`ui/dr-ui/ui/history.slint:103`](../../ui/dr-ui/ui/history.slint#L103), [`ui/dr-ui/ui/history.slint:1`](../../ui/dr-ui/ui/history.slint#L1), [`ui/dr-ui/ui/history.slint:227`](../../ui/dr-ui/ui/history.slint#L227), [`ui/dr-ui/ui/history.slint:53`](../../ui/dr-ui/ui/history.slint#L53), [`ui/dr-ui/ui/widgets.slint:72`](../../ui/dr-ui/ui/widgets.slint#L72) | +| FR-DEV-8 | [`core/dr-gpu/src/detail.rs:397`](../../core/dr-gpu/src/detail.rs#L397), [`core/dr-gpu/src/detail.rs:609`](../../core/dr-gpu/src/detail.rs#L609), [`core/dr-gpu/tests/detail_instances.rs:1`](../../core/dr-gpu/tests/detail_instances.rs#L1), [`core/dr-gpu/tests/spot_removal.rs:1`](../../core/dr-gpu/tests/spot_removal.rs#L1), [`core/dr-pipeline/src/detail.rs:408`](../../core/dr-pipeline/src/detail.rs#L408), [`core/dr-pipeline/src/detail.rs:450`](../../core/dr-pipeline/src/detail.rs#L450), [`core/dr-pipeline/src/detail.rs:485`](../../core/dr-pipeline/src/detail.rs#L485), [`core/dr-pipeline/src/detail.rs:559`](../../core/dr-pipeline/src/detail.rs#L559), [`core/dr-pipeline/src/graph.rs:1087`](../../core/dr-pipeline/src/graph.rs#L1087), [`core/dr-pipeline/src/graph.rs:115`](../../core/dr-pipeline/src/graph.rs#L115), [`core/dr-pipeline/src/graph.rs:247`](../../core/dr-pipeline/src/graph.rs#L247), [`core/dr-pipeline/src/operation.rs:365`](../../core/dr-pipeline/src/operation.rs#L365), [`core/dr-pipeline/src/operation.rs:825`](../../core/dr-pipeline/src/operation.rs#L825), [`core/dr-pipeline/src/sidecar.rs:1104`](../../core/dr-pipeline/src/sidecar.rs#L1104), [`core/dr-pipeline/src/sidecar.rs:1158`](../../core/dr-pipeline/src/sidecar.rs#L1158), [`core/dr-pipeline/src/sidecar.rs:1188`](../../core/dr-pipeline/src/sidecar.rs#L1188), [`core/dr-pipeline/src/sidecar.rs:233`](../../core/dr-pipeline/src/sidecar.rs#L233), [`core/dr-pipeline/src/sidecar.rs:410`](../../core/dr-pipeline/src/sidecar.rs#L410), [`core/dr-pipeline/src/sidecar.rs:910`](../../core/dr-pipeline/src/sidecar.rs#L910), [`core/dr-pipeline/src/spot.rs:115`](../../core/dr-pipeline/src/spot.rs#L115), [`core/dr-pipeline/src/spot.rs:151`](../../core/dr-pipeline/src/spot.rs#L151), [`core/dr-pipeline/src/spot.rs:1`](../../core/dr-pipeline/src/spot.rs#L1), [`core/dr-pipeline/src/spot.rs:207`](../../core/dr-pipeline/src/spot.rs#L207), [`core/dr-pipeline/src/spot.rs:387`](../../core/dr-pipeline/src/spot.rs#L387), [`core/dr-pipeline/src/spot.rs:472`](../../core/dr-pipeline/src/spot.rs#L472), [`core/dr-pipeline/src/spot.rs:582`](../../core/dr-pipeline/src/spot.rs#L582), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`core/dr-pipeline/src/state.rs:103`](../../core/dr-pipeline/src/state.rs#L103), [`core/dr-pipeline/tests/spot_sidecar.rs:1`](../../core/dr-pipeline/tests/spot_sidecar.rs#L1), [`core/dr-pipeline/tests/spots.rs:1`](../../core/dr-pipeline/tests/spots.rs#L1), [`ui/dr-ui/src/develop/repairs.rs:114`](../../ui/dr-ui/src/develop/repairs.rs#L114), [`ui/dr-ui/src/develop/repairs.rs:11`](../../ui/dr-ui/src/develop/repairs.rs#L11), [`ui/dr-ui/src/develop/repairs.rs:197`](../../ui/dr-ui/src/develop/repairs.rs#L197), [`ui/dr-ui/src/develop/repairs.rs:211`](../../ui/dr-ui/src/develop/repairs.rs#L211), [`ui/dr-ui/src/develop/repairs.rs:49`](../../ui/dr-ui/src/develop/repairs.rs#L49), [`ui/dr-ui/src/develop/session.rs:216`](../../ui/dr-ui/src/develop/session.rs#L216), [`ui/dr-ui/src/develop_ui.rs:992`](../../ui/dr-ui/src/develop_ui.rs#L992), [`ui/dr-ui/src/labels.rs:80`](../../ui/dr-ui/src/labels.rs#L80), [`ui/dr-ui/src/lib.rs:2162`](../../ui/dr-ui/src/lib.rs#L2162), [`ui/dr-ui/src/lib.rs:491`](../../ui/dr-ui/src/lib.rs#L491), [`ui/dr-ui/src/spots_ui.rs:19`](../../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/src/spots_ui.rs:1`](../../ui/dr-ui/src/spots_ui.rs#L1), [`ui/dr-ui/src/spots_ui.rs:265`](../../ui/dr-ui/src/spots_ui.rs#L265), [`ui/dr-ui/ui/app.slint:2215`](../../ui/dr-ui/ui/app.slint#L2215), [`ui/dr-ui/ui/app.slint:2458`](../../ui/dr-ui/ui/app.slint#L2458), [`ui/dr-ui/ui/app.slint:3326`](../../ui/dr-ui/ui/app.slint#L3326), [`ui/dr-ui/ui/icons.slint:378`](../../ui/dr-ui/ui/icons.slint#L378), [`ui/dr-ui/ui/session.slint:102`](../../ui/dr-ui/ui/session.slint#L102), [`ui/dr-ui/ui/session.slint:52`](../../ui/dr-ui/ui/session.slint#L52), [`ui/dr-ui/ui/spots.slint:191`](../../ui/dr-ui/ui/spots.slint#L191), [`ui/dr-ui/ui/spots.slint:49`](../../ui/dr-ui/ui/spots.slint#L49), [`ui/dr-ui/ui/spots.slint:6`](../../ui/dr-ui/ui/spots.slint#L6), [`ui/dr-ui/ui/spots.slint:91`](../../ui/dr-ui/ui/spots.slint#L91) | +| FR-DSP-1 | [`core/dr-gpu/src/adjust.rs:1050`](../../core/dr-gpu/src/adjust.rs#L1050), [`core/dr-gpu/src/adjust.rs:2784`](../../core/dr-gpu/src/adjust.rs#L2784), [`core/dr-gpu/src/adjust.rs:2861`](../../core/dr-gpu/src/adjust.rs#L2861), [`core/dr-gpu/src/adjust.rs:2946`](../../core/dr-gpu/src/adjust.rs#L2946), [`core/dr-gpu/src/adjust.rs:44`](../../core/dr-gpu/src/adjust.rs#L44), [`core/dr-gpu/src/lib.rs:174`](../../core/dr-gpu/src/lib.rs#L174), [`core/dr-gpu/src/lib.rs:194`](../../core/dr-gpu/src/lib.rs#L194), [`core/dr-gpu/src/lib.rs:72`](../../core/dr-gpu/src/lib.rs#L72), [`core/dr-gpu/src/lib.rs:95`](../../core/dr-gpu/src/lib.rs#L95), [`core/dr-gpu/tests/capture_sharpen.rs:199`](../../core/dr-gpu/tests/capture_sharpen.rs#L199), [`core/dr-gpu/tests/detail_stage.rs:327`](../../core/dr-gpu/tests/detail_stage.rs#L327), [`core/dr-gpu/tests/local_contrast.rs:263`](../../core/dr-gpu/tests/local_contrast.rs#L263), [`core/dr-gpu/tests/noise_reduction.rs:377`](../../core/dr-gpu/tests/noise_reduction.rs#L377), [`core/dr-pipeline/src/detail.rs:134`](../../core/dr-pipeline/src/detail.rs#L134), [`core/dr-pipeline/src/detail.rs:531`](../../core/dr-pipeline/src/detail.rs#L531), [`core/dr-pipeline/src/graph.rs:928`](../../core/dr-pipeline/src/graph.rs#L928), [`core/dr-pipeline/src/graph.rs:958`](../../core/dr-pipeline/src/graph.rs#L958), [`core/dr-pipeline/src/ops/capture_sharpen.rs:1`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L1), [`core/dr-pipeline/src/ops/capture_sharpen.rs:628`](../../core/dr-pipeline/src/ops/capture_sharpen.rs#L628), [`core/dr-pipeline/src/ops/dehaze.rs:1`](../../core/dr-pipeline/src/ops/dehaze.rs#L1), [`core/dr-pipeline/src/ops/dehaze.rs:564`](../../core/dr-pipeline/src/ops/dehaze.rs#L564), [`core/dr-pipeline/src/ops/local_contrast.rs:1`](../../core/dr-pipeline/src/ops/local_contrast.rs#L1), [`core/dr-pipeline/src/ops/local_contrast.rs:970`](../../core/dr-pipeline/src/ops/local_contrast.rs#L970), [`core/dr-pipeline/src/ops/noise_reduction.rs:694`](../../core/dr-pipeline/src/ops/noise_reduction.rs#L694), [`core/dr-pipeline/src/spot.rs:673`](../../core/dr-pipeline/src/spot.rs#L673), [`ui/dr-ui/src/develop/framing.rs:594`](../../ui/dr-ui/src/develop/framing.rs#L594), [`ui/dr-ui/src/develop/mod.rs:55`](../../ui/dr-ui/src/develop/mod.rs#L55), [`ui/dr-ui/src/develop/render.rs:1017`](../../ui/dr-ui/src/develop/render.rs#L1017), [`ui/dr-ui/src/develop/render.rs:1051`](../../ui/dr-ui/src/develop/render.rs#L1051), [`ui/dr-ui/src/develop/render.rs:1189`](../../ui/dr-ui/src/develop/render.rs#L1189), [`ui/dr-ui/src/develop/render.rs:213`](../../ui/dr-ui/src/develop/render.rs#L213), [`ui/dr-ui/src/develop/render.rs:79`](../../ui/dr-ui/src/develop/render.rs#L79), [`ui/dr-ui/src/lib.rs:1078`](../../ui/dr-ui/src/lib.rs#L1078), [`ui/dr-ui/src/lib.rs:116`](../../ui/dr-ui/src/lib.rs#L116) | +| FR-DSP-3 | [`core/dr-gpu/tests/frame_budget.rs:101`](../../core/dr-gpu/tests/frame_budget.rs#L101), [`core/dr-gpu/tests/local_contrast.rs:328`](../../core/dr-gpu/tests/local_contrast.rs#L328), [`core/dr-pipeline/src/ops/local_contrast.rs:447`](../../core/dr-pipeline/src/ops/local_contrast.rs#L447) | | FR-DSP-4 | [`ui/dr-ui/src/lib.rs:2227`](../../ui/dr-ui/src/lib.rs#L2227), [`ui/dr-ui/src/lib.rs:2406`](../../ui/dr-ui/src/lib.rs#L2406), [`ui/dr-ui/src/refine.rs:1`](../../ui/dr-ui/src/refine.rs#L1), [`ui/dr-ui/ui/app.slint:112`](../../ui/dr-ui/ui/app.slint#L112), [`ui/dr-ui/ui/app.slint:1849`](../../ui/dr-ui/ui/app.slint#L1849), [`ui/dr-ui/ui/histogram.slint:182`](../../ui/dr-ui/ui/histogram.slint#L182), [`ui/dr-ui/ui/histogram.slint:250`](../../ui/dr-ui/ui/histogram.slint#L250) | | FR-DSP-5 | [`core/dr-gpu/tests/frame_budget.rs:101`](../../core/dr-gpu/tests/frame_budget.rs#L101), [`core/dr-gpu/tests/zoom_resolution.rs:135`](../../core/dr-gpu/tests/zoom_resolution.rs#L135), [`core/dr-gpu/tests/zoom_resolution.rs:166`](../../core/dr-gpu/tests/zoom_resolution.rs#L166), [`core/dr-gpu/tests/zoom_resolution.rs:1`](../../core/dr-gpu/tests/zoom_resolution.rs#L1), [`core/dr-gpu/tests/zoom_resolution.rs:216`](../../core/dr-gpu/tests/zoom_resolution.rs#L216) | -| FR-DSP-6 | [`core/dr-pipeline/src/operation.rs:621`](../../core/dr-pipeline/src/operation.rs#L621), [`core/dr-types/src/colour.rs:1`](../../core/dr-types/src/colour.rs#L1), [`ui/dr-ui/src/develop/render.rs:1604`](../../ui/dr-ui/src/develop/render.rs#L1604), [`ui/dr-ui/src/develop/render.rs:252`](../../ui/dr-ui/src/develop/render.rs#L252), [`ui/dr-ui/src/lib.rs:2103`](../../ui/dr-ui/src/lib.rs#L2103), [`ui/dr-ui/src/lib.rs:2944`](../../ui/dr-ui/src/lib.rs#L2944) | -| FR-DSP-7 | [`core/dr-gpu/src/histogram.rs:147`](../../core/dr-gpu/src/histogram.rs#L147), [`core/dr-gpu/src/histogram.rs:1`](../../core/dr-gpu/src/histogram.rs#L1), [`core/dr-gpu/src/histogram.rs:281`](../../core/dr-gpu/src/histogram.rs#L281), [`core/dr-gpu/src/histogram.rs:50`](../../core/dr-gpu/src/histogram.rs#L50), [`core/dr-gpu/src/shaders/histogram.wgsl:1`](../../core/dr-gpu/src/shaders/histogram.wgsl#L1), [`ui/dr-ui/src/develop/render.rs:1395`](../../ui/dr-ui/src/develop/render.rs#L1395), [`ui/dr-ui/src/develop/render.rs:1427`](../../ui/dr-ui/src/develop/render.rs#L1427), [`ui/dr-ui/src/develop/render.rs:285`](../../ui/dr-ui/src/develop/render.rs#L285), [`ui/dr-ui/src/develop/session.rs:116`](../../ui/dr-ui/src/develop/session.rs#L116), [`ui/dr-ui/src/histogram.rs:1`](../../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/lib.rs:2259`](../../ui/dr-ui/src/lib.rs#L2259), [`ui/dr-ui/src/lib.rs:468`](../../ui/dr-ui/src/lib.rs#L468), [`ui/dr-ui/ui/histogram.slint:191`](../../ui/dr-ui/ui/histogram.slint#L191), [`ui/dr-ui/ui/histogram.slint:1`](../../ui/dr-ui/ui/histogram.slint#L1) | -| FR-DSP-8 | [`platform/dr-plat/src/display.rs:1`](../../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/icc.rs:1`](../../platform/dr-plat/src/display/icc.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../../platform/dr-plat/src/display/x11.rs#L1), [`ui/dr-ui/src/develop/render.rs:1159`](../../ui/dr-ui/src/develop/render.rs#L1159), [`ui/dr-ui/src/develop/render.rs:1604`](../../ui/dr-ui/src/develop/render.rs#L1604), [`ui/dr-ui/src/develop/render.rs:1650`](../../ui/dr-ui/src/develop/render.rs#L1650), [`ui/dr-ui/src/develop/render.rs:1669`](../../ui/dr-ui/src/develop/render.rs#L1669), [`ui/dr-ui/src/develop/render.rs:193`](../../ui/dr-ui/src/develop/render.rs#L193), [`ui/dr-ui/src/develop/render.rs:252`](../../ui/dr-ui/src/develop/render.rs#L252), [`ui/dr-ui/src/develop/render.rs:47`](../../ui/dr-ui/src/develop/render.rs#L47), [`ui/dr-ui/src/develop/session.rs:269`](../../ui/dr-ui/src/develop/session.rs#L269), [`ui/dr-ui/src/display_ui.rs:192`](../../ui/dr-ui/src/display_ui.rs#L192), [`ui/dr-ui/src/display_ui.rs:1`](../../ui/dr-ui/src/display_ui.rs#L1), [`ui/dr-ui/src/display_ui.rs:325`](../../ui/dr-ui/src/display_ui.rs#L325), [`ui/dr-ui/src/display_ui.rs:346`](../../ui/dr-ui/src/display_ui.rs#L346), [`ui/dr-ui/src/display_ui.rs:379`](../../ui/dr-ui/src/display_ui.rs#L379), [`ui/dr-ui/src/lib.rs:1284`](../../ui/dr-ui/src/lib.rs#L1284), [`ui/dr-ui/src/lib.rs:2103`](../../ui/dr-ui/src/lib.rs#L2103), [`ui/dr-ui/src/lib.rs:2921`](../../ui/dr-ui/src/lib.rs#L2921), [`ui/dr-ui/src/lib.rs:2944`](../../ui/dr-ui/src/lib.rs#L2944), [`ui/dr-ui/ui/app.slint:130`](../../ui/dr-ui/ui/app.slint#L130), [`ui/dr-ui/ui/app.slint:1835`](../../ui/dr-ui/ui/app.slint#L1835), [`ui/dr-ui/ui/settings.slint:176`](../../ui/dr-ui/ui/settings.slint#L176), [`ui/dr-ui/ui/settings.slint:864`](../../ui/dr-ui/ui/settings.slint#L864) | +| FR-DSP-6 | [`core/dr-pipeline/src/operation.rs:632`](../../core/dr-pipeline/src/operation.rs#L632), [`core/dr-types/src/colour.rs:1`](../../core/dr-types/src/colour.rs#L1), [`ui/dr-ui/src/develop/render.rs:1595`](../../ui/dr-ui/src/develop/render.rs#L1595), [`ui/dr-ui/src/develop/render.rs:248`](../../ui/dr-ui/src/develop/render.rs#L248), [`ui/dr-ui/src/lib.rs:2103`](../../ui/dr-ui/src/lib.rs#L2103), [`ui/dr-ui/src/lib.rs:2944`](../../ui/dr-ui/src/lib.rs#L2944) | +| FR-DSP-7 | [`core/dr-gpu/src/histogram.rs:147`](../../core/dr-gpu/src/histogram.rs#L147), [`core/dr-gpu/src/histogram.rs:1`](../../core/dr-gpu/src/histogram.rs#L1), [`core/dr-gpu/src/histogram.rs:281`](../../core/dr-gpu/src/histogram.rs#L281), [`core/dr-gpu/src/histogram.rs:50`](../../core/dr-gpu/src/histogram.rs#L50), [`core/dr-gpu/src/shaders/histogram.wgsl:1`](../../core/dr-gpu/src/shaders/histogram.wgsl#L1), [`ui/dr-ui/src/develop/render.rs:1386`](../../ui/dr-ui/src/develop/render.rs#L1386), [`ui/dr-ui/src/develop/render.rs:1418`](../../ui/dr-ui/src/develop/render.rs#L1418), [`ui/dr-ui/src/develop/render.rs:276`](../../ui/dr-ui/src/develop/render.rs#L276), [`ui/dr-ui/src/develop/session.rs:116`](../../ui/dr-ui/src/develop/session.rs#L116), [`ui/dr-ui/src/histogram.rs:1`](../../ui/dr-ui/src/histogram.rs#L1), [`ui/dr-ui/src/lib.rs:2259`](../../ui/dr-ui/src/lib.rs#L2259), [`ui/dr-ui/src/lib.rs:468`](../../ui/dr-ui/src/lib.rs#L468), [`ui/dr-ui/ui/histogram.slint:191`](../../ui/dr-ui/ui/histogram.slint#L191), [`ui/dr-ui/ui/histogram.slint:1`](../../ui/dr-ui/ui/histogram.slint#L1) | +| FR-DSP-8 | [`platform/dr-plat/src/display.rs:1`](../../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/icc.rs:1`](../../platform/dr-plat/src/display/icc.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../../platform/dr-plat/src/display/x11.rs#L1), [`ui/dr-ui/src/develop/render.rs:1150`](../../ui/dr-ui/src/develop/render.rs#L1150), [`ui/dr-ui/src/develop/render.rs:1595`](../../ui/dr-ui/src/develop/render.rs#L1595), [`ui/dr-ui/src/develop/render.rs:1641`](../../ui/dr-ui/src/develop/render.rs#L1641), [`ui/dr-ui/src/develop/render.rs:1660`](../../ui/dr-ui/src/develop/render.rs#L1660), [`ui/dr-ui/src/develop/render.rs:189`](../../ui/dr-ui/src/develop/render.rs#L189), [`ui/dr-ui/src/develop/render.rs:248`](../../ui/dr-ui/src/develop/render.rs#L248), [`ui/dr-ui/src/develop/render.rs:47`](../../ui/dr-ui/src/develop/render.rs#L47), [`ui/dr-ui/src/develop/session.rs:269`](../../ui/dr-ui/src/develop/session.rs#L269), [`ui/dr-ui/src/display_ui.rs:192`](../../ui/dr-ui/src/display_ui.rs#L192), [`ui/dr-ui/src/display_ui.rs:1`](../../ui/dr-ui/src/display_ui.rs#L1), [`ui/dr-ui/src/display_ui.rs:325`](../../ui/dr-ui/src/display_ui.rs#L325), [`ui/dr-ui/src/display_ui.rs:346`](../../ui/dr-ui/src/display_ui.rs#L346), [`ui/dr-ui/src/display_ui.rs:379`](../../ui/dr-ui/src/display_ui.rs#L379), [`ui/dr-ui/src/lib.rs:1284`](../../ui/dr-ui/src/lib.rs#L1284), [`ui/dr-ui/src/lib.rs:2103`](../../ui/dr-ui/src/lib.rs#L2103), [`ui/dr-ui/src/lib.rs:2921`](../../ui/dr-ui/src/lib.rs#L2921), [`ui/dr-ui/src/lib.rs:2944`](../../ui/dr-ui/src/lib.rs#L2944), [`ui/dr-ui/ui/app.slint:130`](../../ui/dr-ui/ui/app.slint#L130), [`ui/dr-ui/ui/app.slint:1835`](../../ui/dr-ui/ui/app.slint#L1835), [`ui/dr-ui/ui/settings.slint:176`](../../ui/dr-ui/ui/settings.slint#L176), [`ui/dr-ui/ui/settings.slint:864`](../../ui/dr-ui/ui/settings.slint#L864) | | FR-EXP-1 | [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-10 | [`core/dr-catalog/src/albums.rs:1`](../../core/dr-catalog/src/albums.rs#L1), [`core/dr-types/src/settings.rs:731`](../../core/dr-types/src/settings.rs#L731), [`ui/dr-ui/src/albums_ui.rs:1`](../../ui/dr-ui/src/albums_ui.rs#L1), [`ui/dr-ui/src/collections_ui/controller.rs:129`](../../ui/dr-ui/src/collections_ui/controller.rs#L129), [`ui/dr-ui/src/collections_ui/controller.rs:432`](../../ui/dr-ui/src/collections_ui/controller.rs#L432), [`ui/dr-ui/src/develop_ui.rs:273`](../../ui/dr-ui/src/develop_ui.rs#L273), [`ui/dr-ui/src/export.rs:100`](../../ui/dr-ui/src/export.rs#L100), [`ui/dr-ui/src/export.rs:217`](../../ui/dr-ui/src/export.rs#L217), [`ui/dr-ui/src/export.rs:588`](../../ui/dr-ui/src/export.rs#L588), [`ui/dr-ui/src/lib.rs:1627`](../../ui/dr-ui/src/lib.rs#L1627), [`ui/dr-ui/src/library_ui/controller.rs:205`](../../ui/dr-ui/src/library_ui/controller.rs#L205), [`ui/dr-ui/src/library_ui/controller.rs:934`](../../ui/dr-ui/src/library_ui/controller.rs#L934), [`ui/dr-ui/src/library_ui/controller.rs:974`](../../ui/dr-ui/src/library_ui/controller.rs#L974), [`ui/dr-ui/src/library_ui/window.rs:359`](../../ui/dr-ui/src/library_ui/window.rs#L359), [`ui/dr-ui/src/saf.rs:1`](../../ui/dr-ui/src/saf.rs#L1), [`ui/dr-ui/ui/albums.slint:1`](../../ui/dr-ui/ui/albums.slint#L1), [`ui/dr-ui/ui/app.slint:3559`](../../ui/dr-ui/ui/app.slint#L3559), [`ui/dr-ui/ui/collections.slint:789`](../../ui/dr-ui/ui/collections.slint#L789), [`ui/dr-ui/ui/export.slint:204`](../../ui/dr-ui/ui/export.slint#L204) | -| FR-EXP-2 | [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/error.rs:26`](../../core/dr-export/src/error.rs#L26), [`core/dr-export/src/icc.rs:1`](../../core/dr-export/src/icc.rs#L1), [`core/dr-export/src/lib.rs:157`](../../core/dr-export/src/lib.rs#L157), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/lib.rs:57`](../../core/dr-export/src/lib.rs#L57), [`core/dr-gpu/src/adjust.rs:3127`](../../core/dr-gpu/src/adjust.rs#L3127), [`core/dr-pipeline/src/graph.rs:841`](../../core/dr-pipeline/src/graph.rs#L841), [`core/dr-pipeline/src/graph.rs:972`](../../core/dr-pipeline/src/graph.rs#L972), [`core/dr-pipeline/src/operation.rs:621`](../../core/dr-pipeline/src/operation.rs#L621), [`core/dr-types/src/colour.rs:1`](../../core/dr-types/src/colour.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:976`](../../core/dr-types/src/settings.rs#L976), [`ui/dr-ui/src/develop/render.rs:1669`](../../ui/dr-ui/src/develop/render.rs#L1669), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | +| FR-EXP-2 | [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/error.rs:26`](../../core/dr-export/src/error.rs#L26), [`core/dr-export/src/icc.rs:1`](../../core/dr-export/src/icc.rs#L1), [`core/dr-export/src/lib.rs:157`](../../core/dr-export/src/lib.rs#L157), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/lib.rs:57`](../../core/dr-export/src/lib.rs#L57), [`core/dr-gpu/src/adjust.rs:3219`](../../core/dr-gpu/src/adjust.rs#L3219), [`core/dr-pipeline/src/graph.rs:841`](../../core/dr-pipeline/src/graph.rs#L841), [`core/dr-pipeline/src/operation.rs:632`](../../core/dr-pipeline/src/operation.rs#L632), [`core/dr-types/src/colour.rs:1`](../../core/dr-types/src/colour.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`core/dr-types/src/settings.rs:976`](../../core/dr-types/src/settings.rs#L976), [`ui/dr-ui/src/develop/render.rs:1660`](../../ui/dr-ui/src/develop/render.rs#L1660), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-3 | [`core/dr-export/src/lib.rs:186`](../../core/dr-export/src/lib.rs#L186), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/size.rs:136`](../../core/dr-export/src/size.rs#L136), [`core/dr-export/src/size.rs:1`](../../core/dr-export/src/size.rs#L1), [`core/dr-export/src/size.rs:25`](../../core/dr-export/src/size.rs#L25), [`core/dr-export/src/size.rs:84`](../../core/dr-export/src/size.rs#L84), [`core/dr-types/src/settings.rs:1021`](../../core/dr-types/src/settings.rs#L1021), [`core/dr-types/src/settings.rs:1029`](../../core/dr-types/src/settings.rs#L1029), [`core/dr-types/src/settings.rs:1045`](../../core/dr-types/src/settings.rs#L1045), [`core/dr-types/src/settings.rs:1114`](../../core/dr-types/src/settings.rs#L1114), [`core/dr-types/src/settings.rs:1142`](../../core/dr-types/src/settings.rs#L1142), [`core/dr-types/src/settings.rs:1153`](../../core/dr-types/src/settings.rs#L1153), [`core/dr-types/src/settings.rs:1159`](../../core/dr-types/src/settings.rs#L1159), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/src/settings_ui.rs:256`](../../ui/dr-ui/src/settings_ui.rs#L256), [`ui/dr-ui/src/settings_ui.rs:269`](../../ui/dr-ui/src/settings_ui.rs#L269), [`ui/dr-ui/src/settings_ui.rs:288`](../../ui/dr-ui/src/settings_ui.rs#L288), [`ui/dr-ui/src/settings_ui.rs:701`](../../ui/dr-ui/src/settings_ui.rs#L701), [`ui/dr-ui/ui/export.slint:138`](../../ui/dr-ui/ui/export.slint#L138), [`ui/dr-ui/ui/export.slint:148`](../../ui/dr-ui/ui/export.slint#L148) | | FR-EXP-4 | [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/sharpen.rs:1`](../../core/dr-export/src/sharpen.rs#L1), [`core/dr-export/src/size.rs:1`](../../core/dr-export/src/size.rs#L1), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | | FR-EXP-5 | [`ui/dr-ui/src/settings_store.rs:1`](../../ui/dr-ui/src/settings_store.rs#L1) | | FR-EXP-6 | [`core/dr-catalog/src/albums.rs:1`](../../core/dr-catalog/src/albums.rs#L1), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-export/src/name.rs:1`](../../core/dr-export/src/name.rs#L1), [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/albums_ui.rs:1`](../../ui/dr-ui/src/albums_ui.rs#L1), [`ui/dr-ui/src/export.rs:1`](../../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/lib.rs:652`](../../ui/dr-ui/src/lib.rs#L652), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1), [`ui/dr-ui/ui/albums.slint:1`](../../ui/dr-ui/ui/albums.slint#L1) | | FR-EXP-7 | [`ui/dr-ui/src/activity.rs:83`](../../ui/dr-ui/src/activity.rs#L83), [`ui/dr-ui/src/develop_ui.rs:370`](../../ui/dr-ui/src/develop_ui.rs#L370), [`ui/dr-ui/src/export.rs:1122`](../../ui/dr-ui/src/export.rs#L1122), [`ui/dr-ui/src/export.rs:1`](../../ui/dr-ui/src/export.rs#L1), [`ui/dr-ui/src/lib.rs:293`](../../ui/dr-ui/src/lib.rs#L293), [`ui/dr-ui/src/lib.rs:652`](../../ui/dr-ui/src/lib.rs#L652), [`ui/dr-ui/src/lib.rs:698`](../../ui/dr-ui/src/lib.rs#L698), [`ui/dr-ui/src/lib.rs:727`](../../ui/dr-ui/src/lib.rs#L727), [`ui/dr-ui/src/library_ui/controller.rs:1099`](../../ui/dr-ui/src/library_ui/controller.rs#L1099), [`ui/dr-ui/src/library_ui/controller.rs:1111`](../../ui/dr-ui/src/library_ui/controller.rs#L1111), [`ui/dr-ui/src/library_ui/controller.rs:1123`](../../ui/dr-ui/src/library_ui/controller.rs#L1123), [`ui/dr-ui/src/library_ui/controller.rs:768`](../../ui/dr-ui/src/library_ui/controller.rs#L768), [`ui/dr-ui/src/library_ui/controller.rs:868`](../../ui/dr-ui/src/library_ui/controller.rs#L868), [`ui/dr-ui/src/library_ui/controller.rs:925`](../../ui/dr-ui/src/library_ui/controller.rs#L925), [`ui/dr-ui/src/library_ui/sync.rs:101`](../../ui/dr-ui/src/library_ui/sync.rs#L101), [`ui/dr-ui/src/settings_ui.rs:394`](../../ui/dr-ui/src/settings_ui.rs#L394), [`ui/dr-ui/ui/app.slint:1090`](../../ui/dr-ui/ui/app.slint#L1090), [`ui/dr-ui/ui/app.slint:1521`](../../ui/dr-ui/ui/app.slint#L1521), [`ui/dr-ui/ui/app.slint:2551`](../../ui/dr-ui/ui/app.slint#L2551), [`ui/dr-ui/ui/app.slint:3459`](../../ui/dr-ui/ui/app.slint#L3459), [`ui/dr-ui/ui/app.slint:687`](../../ui/dr-ui/ui/app.slint#L687), [`ui/dr-ui/ui/app.slint:704`](../../ui/dr-ui/ui/app.slint#L704), [`ui/dr-ui/ui/app.slint:940`](../../ui/dr-ui/ui/app.slint#L940), [`ui/dr-ui/ui/export.slint:1`](../../ui/dr-ui/ui/export.slint#L1), [`ui/dr-ui/ui/export.slint:246`](../../ui/dr-ui/ui/export.slint#L246), [`ui/dr-ui/ui/library.slint:2009`](../../ui/dr-ui/ui/library.slint#L2009), [`ui/dr-ui/ui/library.slint:2018`](../../ui/dr-ui/ui/library.slint#L2018), [`ui/dr-ui/ui/library.slint:3177`](../../ui/dr-ui/ui/library.slint#L3177), [`ui/dr-ui/ui/library.slint:5205`](../../ui/dr-ui/ui/library.slint#L5205) | | FR-EXP-8 | [`core/dr-decode/src/lib.rs:357`](../../core/dr-decode/src/lib.rs#L357), [`core/dr-decode/src/lib.rs:381`](../../core/dr-decode/src/lib.rs#L381), [`core/dr-decode/src/lib.rs:395`](../../core/dr-decode/src/lib.rs#L395), [`core/dr-decode/src/lib.rs:75`](../../core/dr-decode/src/lib.rs#L75), [`core/dr-decode/src/lib.rs:83`](../../core/dr-decode/src/lib.rs#L83), [`core/dr-decode/src/lib.rs:86`](../../core/dr-decode/src/lib.rs#L86), [`core/dr-decode/src/locate.rs:1233`](../../core/dr-decode/src/locate.rs#L1233), [`core/dr-decode/src/locate.rs:1292`](../../core/dr-decode/src/locate.rs#L1292), [`core/dr-decode/src/locate.rs:359`](../../core/dr-decode/src/locate.rs#L359), [`core/dr-decode/src/locate.rs:556`](../../core/dr-decode/src/locate.rs#L556), [`core/dr-decode/src/locate.rs:640`](../../core/dr-decode/src/locate.rs#L640), [`core/dr-decode/src/locate.rs:653`](../../core/dr-decode/src/locate.rs#L653), [`core/dr-decode/src/locate.rs:736`](../../core/dr-decode/src/locate.rs#L736), [`core/dr-export/examples/export.rs:99`](../../core/dr-export/examples/export.rs#L99), [`core/dr-export/src/encode.rs:117`](../../core/dr-export/src/encode.rs#L117), [`core/dr-export/src/encode.rs:161`](../../core/dr-export/src/encode.rs#L161), [`core/dr-export/src/encode.rs:1`](../../core/dr-export/src/encode.rs#L1), [`core/dr-export/src/encode.rs:206`](../../core/dr-export/src/encode.rs#L206), [`core/dr-export/src/encode.rs:235`](../../core/dr-export/src/encode.rs#L235), [`core/dr-export/src/encode.rs:311`](../../core/dr-export/src/encode.rs#L311), [`core/dr-export/src/encode.rs:325`](../../core/dr-export/src/encode.rs#L325), [`core/dr-export/src/encode.rs:408`](../../core/dr-export/src/encode.rs#L408), [`core/dr-export/src/encode.rs:456`](../../core/dr-export/src/encode.rs#L456), [`core/dr-export/src/encode.rs:70`](../../core/dr-export/src/encode.rs#L70), [`core/dr-export/src/encode.rs:795`](../../core/dr-export/src/encode.rs#L795), [`core/dr-export/src/encode.rs:809`](../../core/dr-export/src/encode.rs#L809), [`core/dr-export/src/encode.rs:850`](../../core/dr-export/src/encode.rs#L850), [`core/dr-export/src/encode.rs:898`](../../core/dr-export/src/encode.rs#L898), [`core/dr-export/src/exif.rs:1`](../../core/dr-export/src/exif.rs#L1), [`core/dr-export/src/lib.rs:140`](../../core/dr-export/src/lib.rs#L140), [`core/dr-export/src/metadata.rs:1`](../../core/dr-export/src/metadata.rs#L1), [`core/dr-export/src/metadata.rs:41`](../../core/dr-export/src/metadata.rs#L41), [`core/dr-export/src/metadata.rs:74`](../../core/dr-export/src/metadata.rs#L74), [`core/dr-types/src/lib.rs:655`](../../core/dr-types/src/lib.rs#L655), [`core/dr-types/src/settings.rs:671`](../../core/dr-types/src/settings.rs#L671), [`ui/dr-ui/src/decoder_seam.rs:255`](../../ui/dr-ui/src/decoder_seam.rs#L255), [`ui/dr-ui/src/develop/session.rs:37`](../../ui/dr-ui/src/develop/session.rs#L37), [`ui/dr-ui/src/develop/session.rs:417`](../../ui/dr-ui/src/develop/session.rs#L417), [`ui/dr-ui/src/develop/session.rs:529`](../../ui/dr-ui/src/develop/session.rs#L529), [`ui/dr-ui/src/export.rs:555`](../../ui/dr-ui/src/export.rs#L555), [`ui/dr-ui/src/export.rs:740`](../../ui/dr-ui/src/export.rs#L740), [`ui/dr-ui/src/export.rs:786`](../../ui/dr-ui/src/export.rs#L786), [`ui/dr-ui/src/export.rs:814`](../../ui/dr-ui/src/export.rs#L814), [`ui/dr-ui/src/export.rs:851`](../../ui/dr-ui/src/export.rs#L851), [`ui/dr-ui/src/export.rs:952`](../../ui/dr-ui/src/export.rs#L952), [`ui/dr-ui/src/export.rs:970`](../../ui/dr-ui/src/export.rs#L970), [`ui/dr-ui/src/lib.rs:293`](../../ui/dr-ui/src/lib.rs#L293), [`ui/dr-ui/src/lib.rs:317`](../../ui/dr-ui/src/lib.rs#L317), [`ui/dr-ui/src/lib.rs:684`](../../ui/dr-ui/src/lib.rs#L684), [`ui/dr-ui/src/settings_ui.rs:1`](../../ui/dr-ui/src/settings_ui.rs#L1) | -| FR-EXP-9 | [`core/dr-decode/src/lib.rs:537`](../../core/dr-decode/src/lib.rs#L537), [`core/dr-export/src/lib.rs:132`](../../core/dr-export/src/lib.rs#L132), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-gpu/src/adjust.rs:1392`](../../core/dr-gpu/src/adjust.rs#L1392), [`ui/dr-ui/examples/face_native.rs:1`](../../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/decoder_seam.rs:255`](../../ui/dr-ui/src/decoder_seam.rs#L255), [`ui/dr-ui/src/develop/mask_ops.rs:1130`](../../ui/dr-ui/src/develop/mask_ops.rs#L1130), [`ui/dr-ui/src/develop/render.rs:588`](../../ui/dr-ui/src/develop/render.rs#L588), [`ui/dr-ui/src/develop/render.rs:626`](../../ui/dr-ui/src/develop/render.rs#L626), [`ui/dr-ui/src/lib.rs:652`](../../ui/dr-ui/src/lib.rs#L652), [`ui/dr-ui/src/library/sweep.rs:511`](../../ui/dr-ui/src/library/sweep.rs#L511), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | +| FR-EXP-9 | [`core/dr-decode/src/lib.rs:537`](../../core/dr-decode/src/lib.rs#L537), [`core/dr-export/src/lib.rs:132`](../../core/dr-export/src/lib.rs#L132), [`core/dr-export/src/lib.rs:1`](../../core/dr-export/src/lib.rs#L1), [`core/dr-gpu/src/adjust.rs:1484`](../../core/dr-gpu/src/adjust.rs#L1484), [`ui/dr-ui/examples/face_native.rs:1`](../../ui/dr-ui/examples/face_native.rs#L1), [`ui/dr-ui/src/decoder_seam.rs:255`](../../ui/dr-ui/src/decoder_seam.rs#L255), [`ui/dr-ui/src/develop/mask_ops.rs:1130`](../../ui/dr-ui/src/develop/mask_ops.rs#L1130), [`ui/dr-ui/src/develop/render.rs:579`](../../ui/dr-ui/src/develop/render.rs#L579), [`ui/dr-ui/src/develop/render.rs:617`](../../ui/dr-ui/src/develop/render.rs#L617), [`ui/dr-ui/src/lib.rs:652`](../../ui/dr-ui/src/lib.rs#L652), [`ui/dr-ui/src/library/sweep.rs:511`](../../ui/dr-ui/src/library/sweep.rs#L511), [`ui/dr-ui/tests/export_ignores_the_viewport.rs:1`](../../ui/dr-ui/tests/export_ignores_the_viewport.rs#L1) | | FR-INF-1 | [`ui/dr-ui/src/lib.rs:1464`](../../ui/dr-ui/src/lib.rs#L1464), [`ui/dr-ui/ui/settings.slint:824`](../../ui/dr-ui/ui/settings.slint#L824) | | FR-MRG-1 | [`core/dr-pano/src/align.rs:1`](../../core/dr-pano/src/align.rs#L1), [`core/dr-pano/src/lib.rs:1`](../../core/dr-pano/src/lib.rs#L1), [`ui/dr-ui/src/lib.rs:1890`](../../ui/dr-ui/src/lib.rs#L1890), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1), [`ui/dr-ui/src/merge_ui.rs:1`](../../ui/dr-ui/src/merge_ui.rs#L1), [`ui/dr-ui/ui/app.slint:1526`](../../ui/dr-ui/ui/app.slint#L1526), [`ui/dr-ui/ui/app.slint:589`](../../ui/dr-ui/ui/app.slint#L589), [`ui/dr-ui/ui/library.slint:2023`](../../ui/dr-ui/ui/library.slint#L2023), [`ui/dr-ui/ui/library.slint:5162`](../../ui/dr-ui/ui/library.slint#L5162), [`ui/dr-ui/ui/merge.slint:1`](../../ui/dr-ui/ui/merge.slint#L1) | | FR-MRG-10 | [`core/dr-gpu/src/merge.rs:1`](../../core/dr-gpu/src/merge.rs#L1), [`core/dr-gpu/src/shaders/merge.wgsl:1`](../../core/dr-gpu/src/shaders/merge.wgsl#L1), [`core/dr-pano/src/lib.rs:1`](../../core/dr-pano/src/lib.rs#L1) | | FR-MRG-11 | [`core/dr-gpu/src/merge.rs:1`](../../core/dr-gpu/src/merge.rs#L1), [`core/dr-gpu/src/shaders/merge.wgsl:1`](../../core/dr-gpu/src/shaders/merge.wgsl#L1) | -| FR-MRG-2 | [`core/dr-gpu/src/adjust.rs:1415`](../../core/dr-gpu/src/adjust.rs#L1415), [`core/dr-gpu/src/adjust.rs:1542`](../../core/dr-gpu/src/adjust.rs#L1542), [`core/dr-gpu/src/adjust.rs:526`](../../core/dr-gpu/src/adjust.rs#L526), [`core/dr-gpu/src/adjust.rs:94`](../../core/dr-gpu/src/adjust.rs#L94), [`core/dr-pipeline/src/graph.rs:858`](../../core/dr-pipeline/src/graph.rs#L858), [`core/dr-pipeline/src/operation.rs:1071`](../../core/dr-pipeline/src/operation.rs#L1071), [`core/dr-pipeline/src/operation.rs:2364`](../../core/dr-pipeline/src/operation.rs#L2364), [`core/dr-pipeline/src/operation.rs:2404`](../../core/dr-pipeline/src/operation.rs#L2404), [`core/dr-pipeline/src/operation.rs:514`](../../core/dr-pipeline/src/operation.rs#L514), [`core/dr-pipeline/src/operation.rs:707`](../../core/dr-pipeline/src/operation.rs#L707), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1) | +| FR-MRG-2 | [`core/dr-gpu/src/adjust.rs:1507`](../../core/dr-gpu/src/adjust.rs#L1507), [`core/dr-gpu/src/adjust.rs:1634`](../../core/dr-gpu/src/adjust.rs#L1634), [`core/dr-gpu/src/adjust.rs:528`](../../core/dr-gpu/src/adjust.rs#L528), [`core/dr-gpu/src/adjust.rs:94`](../../core/dr-gpu/src/adjust.rs#L94), [`core/dr-pipeline/src/graph.rs:858`](../../core/dr-pipeline/src/graph.rs#L858), [`core/dr-pipeline/src/operation.rs:1111`](../../core/dr-pipeline/src/operation.rs#L1111), [`core/dr-pipeline/src/operation.rs:2437`](../../core/dr-pipeline/src/operation.rs#L2437), [`core/dr-pipeline/src/operation.rs:2477`](../../core/dr-pipeline/src/operation.rs#L2477), [`core/dr-pipeline/src/operation.rs:514`](../../core/dr-pipeline/src/operation.rs#L514), [`core/dr-pipeline/src/operation.rs:718`](../../core/dr-pipeline/src/operation.rs#L718), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1) | | FR-MRG-3 | [`core/dr-decode/examples/linear_dng.rs:1`](../../core/dr-decode/examples/linear_dng.rs#L1), [`core/dr-decode/src/lib.rs:128`](../../core/dr-decode/src/lib.rs#L128), [`core/dr-decode/src/lib.rs:135`](../../core/dr-decode/src/lib.rs#L135), [`core/dr-decode/src/lib.rs:580`](../../core/dr-decode/src/lib.rs#L580), [`core/dr-decode/src/profile.rs:397`](../../core/dr-decode/src/profile.rs#L397), [`core/dr-export/src/dng.rs:1`](../../core/dr-export/src/dng.rs#L1), [`core/dr-gpu/src/demosaic.rs:282`](../../core/dr-gpu/src/demosaic.rs#L282), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1) | | FR-MRG-4 | [`core/dr-export/src/inscribed.rs:1`](../../core/dr-export/src/inscribed.rs#L1), [`core/dr-pano/src/fill.rs:1`](../../core/dr-pano/src/fill.rs#L1), [`core/dr-pano/src/migan.rs:1`](../../core/dr-pano/src/migan.rs#L1), [`core/dr-pano/src/projection.rs:1`](../../core/dr-pano/src/projection.rs#L1), [`ui/dr-ui/src/library/paths.rs:365`](../../ui/dr-ui/src/library/paths.rs#L365), [`ui/dr-ui/src/library/paths.rs:369`](../../ui/dr-ui/src/library/paths.rs#L369), [`ui/dr-ui/src/merge.rs:161`](../../ui/dr-ui/src/merge.rs#L161), [`ui/dr-ui/src/merge_ui.rs:1`](../../ui/dr-ui/src/merge_ui.rs#L1), [`ui/dr-ui/ui/merge.slint:1`](../../ui/dr-ui/ui/merge.slint#L1), [`ui/dr-ui/ui/merge.slint:50`](../../ui/dr-ui/ui/merge.slint#L50) | | FR-MRG-5 | [`core/dr-pano/src/align.rs:1`](../../core/dr-pano/src/align.rs#L1), [`ui/dr-ui/src/merge.rs:1`](../../ui/dr-ui/src/merge.rs#L1), [`ui/dr-ui/src/merge_ui.rs:1`](../../ui/dr-ui/src/merge_ui.rs#L1), [`ui/dr-ui/ui/merge.slint:1`](../../ui/dr-ui/ui/merge.slint#L1) | @@ -138,7 +138,7 @@ _None._ | FR-PLAT-AND-2 | [`core/dr-catalog/src/walk.rs:1000`](../../core/dr-catalog/src/walk.rs#L1000), [`core/dr-catalog/src/walk.rs:432`](../../core/dr-catalog/src/walk.rs#L432), [`core/dr-sync-folder/src/lib.rs:242`](../../core/dr-sync-folder/src/lib.rs#L242), [`core/dr-sync-folder/src/tests.rs:51`](../../core/dr-sync-folder/src/tests.rs#L51), [`core/dr-sync/src/error.rs:113`](../../core/dr-sync/src/error.rs#L113), [`core/dr-sync/src/error.rs:195`](../../core/dr-sync/src/error.rs#L195), [`core/dr-sync/src/scan.rs:211`](../../core/dr-sync/src/scan.rs#L211), [`core/dr-sync/src/scan.rs:519`](../../core/dr-sync/src/scan.rs#L519), [`core/dr-sync/src/scan.rs:545`](../../core/dr-sync/src/scan.rs#L545), [`core/dr-sync/src/scan.rs:574`](../../core/dr-sync/src/scan.rs#L574), [`ui/dr-ui/src/library/scan.rs:127`](../../ui/dr-ui/src/library/scan.rs#L127), [`ui/dr-ui/src/library/scan.rs:180`](../../ui/dr-ui/src/library/scan.rs#L180), [`ui/dr-ui/src/library/scan.rs:211`](../../ui/dr-ui/src/library/scan.rs#L211), [`ui/dr-ui/src/library/scan.rs:636`](../../ui/dr-ui/src/library/scan.rs#L636), [`ui/dr-ui/src/library_ui/controller.rs:344`](../../ui/dr-ui/src/library_ui/controller.rs#L344), [`ui/dr-ui/src/library_ui/controller.rs:592`](../../ui/dr-ui/src/library_ui/controller.rs#L592), [`ui/dr-ui/src/library_ui/offline.rs:569`](../../ui/dr-ui/src/library_ui/offline.rs#L569), [`ui/dr-ui/src/library_ui/open.rs:427`](../../ui/dr-ui/src/library_ui/open.rs#L427), [`ui/dr-ui/src/library_ui/open.rs:536`](../../ui/dr-ui/src/library_ui/open.rs#L536) | | FR-PLAT-AND-3 | [`core/dr-catalog/src/jobs.rs:1`](../../core/dr-catalog/src/jobs.rs#L1), [`core/dr-catalog/src/runner.rs:1`](../../core/dr-catalog/src/runner.rs#L1), [`core/dr-catalog/tests/every_queued_kind_has_a_consumer.rs:1`](../../core/dr-catalog/tests/every_queued_kind_has_a_consumer.rs#L1) | | FR-PLAT-AND-4 | [`core/dr-catalog/src/runner.rs:1`](../../core/dr-catalog/src/runner.rs#L1) | -| FR-PLAT-AND-5 | [`apps/darkroom-android/src/lib.rs:166`](../../apps/darkroom-android/src/lib.rs#L166), [`core/dr-gpu/src/adjust.rs:1314`](../../core/dr-gpu/src/adjust.rs#L1314), [`core/dr-gpu/src/detail.rs:161`](../../core/dr-gpu/src/detail.rs#L161), [`core/dr-gpu/src/detail.rs:547`](../../core/dr-gpu/src/detail.rs#L547), [`core/dr-gpu/tests/detail_stage.rs:417`](../../core/dr-gpu/tests/detail_stage.rs#L417), [`ui/dr-ui/src/develop/render.rs:561`](../../ui/dr-ui/src/develop/render.rs#L561), [`ui/dr-ui/src/identity_ui.rs:125`](../../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:1236`](../../ui/dr-ui/src/lib.rs#L1236), [`ui/dr-ui/src/lib.rs:1635`](../../ui/dr-ui/src/lib.rs#L1635), [`ui/dr-ui/src/memory.rs:163`](../../ui/dr-ui/src/memory.rs#L163), [`ui/dr-ui/src/memory.rs:1`](../../ui/dr-ui/src/memory.rs#L1) | +| FR-PLAT-AND-5 | [`apps/darkroom-android/src/lib.rs:166`](../../apps/darkroom-android/src/lib.rs#L166), [`core/dr-gpu/src/adjust.rs:1399`](../../core/dr-gpu/src/adjust.rs#L1399), [`core/dr-gpu/src/detail.rs:161`](../../core/dr-gpu/src/detail.rs#L161), [`core/dr-gpu/src/detail.rs:533`](../../core/dr-gpu/src/detail.rs#L533), [`core/dr-gpu/tests/detail_stage.rs:415`](../../core/dr-gpu/tests/detail_stage.rs#L415), [`ui/dr-ui/src/develop/render.rs:552`](../../ui/dr-ui/src/develop/render.rs#L552), [`ui/dr-ui/src/identity_ui.rs:125`](../../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:1236`](../../ui/dr-ui/src/lib.rs#L1236), [`ui/dr-ui/src/lib.rs:1635`](../../ui/dr-ui/src/lib.rs#L1635), [`ui/dr-ui/src/memory.rs:163`](../../ui/dr-ui/src/memory.rs#L163), [`ui/dr-ui/src/memory.rs:1`](../../ui/dr-ui/src/memory.rs#L1) | | FR-PLAT-AND-6 | [`apps/darkroom-android/src/lib.rs:443`](../../apps/darkroom-android/src/lib.rs#L443) | | FR-PLAT-LIN-1 | [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`platform/dr-plat/src/dirs.rs:1`](../../platform/dr-plat/src/dirs.rs#L1), [`platform/dr-plat/src/storage.rs:344`](../../platform/dr-plat/src/storage.rs#L344), [`ui/dr-ui/src/lib.rs:1413`](../../ui/dr-ui/src/lib.rs#L1413), [`ui/dr-ui/src/preset_store.rs:1`](../../ui/dr-ui/src/preset_store.rs#L1), [`ui/dr-ui/src/settings_store.rs:1`](../../ui/dr-ui/src/settings_store.rs#L1) | | FR-PLAT-LIN-2 | [`platform/dr-plat/src/display.rs:1`](../../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/display/wayland.rs:1`](../../platform/dr-plat/src/display/wayland.rs#L1), [`platform/dr-plat/src/display/x11.rs:1`](../../platform/dr-plat/src/display/x11.rs#L1) | @@ -153,7 +153,7 @@ _None._ | FR-UI-1 | [`core/dr-types/src/settings.rs:1390`](../../core/dr-types/src/settings.rs#L1390), [`core/dr-types/src/settings.rs:492`](../../core/dr-types/src/settings.rs#L492), [`core/dr-types/src/settings.rs:512`](../../core/dr-types/src/settings.rs#L512), [`ui/dr-ui/src/develop_ui.rs:204`](../../ui/dr-ui/src/develop_ui.rs#L204), [`ui/dr-ui/src/lib.rs:124`](../../ui/dr-ui/src/lib.rs#L124), [`ui/dr-ui/src/lib.rs:139`](../../ui/dr-ui/src/lib.rs#L139), [`ui/dr-ui/src/lib.rs:161`](../../ui/dr-ui/src/lib.rs#L161), [`ui/dr-ui/src/lib.rs:3216`](../../ui/dr-ui/src/lib.rs#L3216), [`ui/dr-ui/src/lib.rs:3235`](../../ui/dr-ui/src/lib.rs#L3235), [`ui/dr-ui/src/lib.rs:3262`](../../ui/dr-ui/src/lib.rs#L3262), [`ui/dr-ui/src/lib.rs:3313`](../../ui/dr-ui/src/lib.rs#L3313), [`ui/dr-ui/src/lib.rs:3346`](../../ui/dr-ui/src/lib.rs#L3346), [`ui/dr-ui/src/library_ui/grid.rs:242`](../../ui/dr-ui/src/library_ui/grid.rs#L242), [`ui/dr-ui/src/masks_ui.rs:1608`](../../ui/dr-ui/src/masks_ui.rs#L1608), [`ui/dr-ui/src/settings_ui.rs:143`](../../ui/dr-ui/src/settings_ui.rs#L143), [`ui/dr-ui/ui/adjust.slint:1000`](../../ui/dr-ui/ui/adjust.slint#L1000), [`ui/dr-ui/ui/app.slint:3097`](../../ui/dr-ui/ui/app.slint#L3097), [`ui/dr-ui/ui/app.slint:666`](../../ui/dr-ui/ui/app.slint#L666), [`ui/dr-ui/ui/app.slint:811`](../../ui/dr-ui/ui/app.slint#L811), [`ui/dr-ui/ui/identity.slint:249`](../../ui/dr-ui/ui/identity.slint#L249), [`ui/dr-ui/ui/library.slint:1447`](../../ui/dr-ui/ui/library.slint#L1447), [`ui/dr-ui/ui/settings.slint:129`](../../ui/dr-ui/ui/settings.slint#L129), [`ui/dr-ui/ui/settings.slint:660`](../../ui/dr-ui/ui/settings.slint#L660), [`ui/dr-ui/ui/toolrail.slint:177`](../../ui/dr-ui/ui/toolrail.slint#L177), [`ui/dr-ui/ui/toolrail.slint:91`](../../ui/dr-ui/ui/toolrail.slint#L91), [`ui/dr-ui/ui/widgets.slint:1117`](../../ui/dr-ui/ui/widgets.slint#L1117) | | FR-UI-2 | [`ui/dr-ui/src/collections_ui/controller.rs:45`](../../ui/dr-ui/src/collections_ui/controller.rs#L45), [`ui/dr-ui/src/collections_ui/controller.rs:83`](../../ui/dr-ui/src/collections_ui/controller.rs#L83), [`ui/dr-ui/src/collections_ui/drag.rs:246`](../../ui/dr-ui/src/collections_ui/drag.rs#L246), [`ui/dr-ui/src/collections_ui/drag.rs:256`](../../ui/dr-ui/src/collections_ui/drag.rs#L256), [`ui/dr-ui/src/collections_ui/press.rs:453`](../../ui/dr-ui/src/collections_ui/press.rs#L453), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:121`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L121), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:138`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L138), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:415`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L415), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/gestures.rs:1`](../../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:124`](../../ui/dr-ui/src/lib.rs#L124), [`ui/dr-ui/src/library_ui/filter_bar.rs:351`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L351), [`ui/dr-ui/src/library_ui/grid.rs:242`](../../ui/dr-ui/src/library_ui/grid.rs#L242), [`ui/dr-ui/src/library_ui/window.rs:1000`](../../ui/dr-ui/src/library_ui/window.rs#L1000), [`ui/dr-ui/tests/scroll_cue.rs:1`](../../ui/dr-ui/tests/scroll_cue.rs#L1), [`ui/dr-ui/ui/app.slint:137`](../../ui/dr-ui/ui/app.slint#L137), [`ui/dr-ui/ui/app.slint:3494`](../../ui/dr-ui/ui/app.slint#L3494), [`ui/dr-ui/ui/app.slint:795`](../../ui/dr-ui/ui/app.slint#L795), [`ui/dr-ui/ui/collections.slint:1354`](../../ui/dr-ui/ui/collections.slint#L1354), [`ui/dr-ui/ui/controls.slint:626`](../../ui/dr-ui/ui/controls.slint#L626), [`ui/dr-ui/ui/gestures.slint:1`](../../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/library.slint:1334`](../../ui/dr-ui/ui/library.slint#L1334), [`ui/dr-ui/ui/library.slint:1367`](../../ui/dr-ui/ui/library.slint#L1367), [`ui/dr-ui/ui/library.slint:1691`](../../ui/dr-ui/ui/library.slint#L1691), [`ui/dr-ui/ui/library.slint:1698`](../../ui/dr-ui/ui/library.slint#L1698), [`ui/dr-ui/ui/library.slint:1799`](../../ui/dr-ui/ui/library.slint#L1799), [`ui/dr-ui/ui/library.slint:3135`](../../ui/dr-ui/ui/library.slint#L3135), [`ui/dr-ui/ui/library.slint:572`](../../ui/dr-ui/ui/library.slint#L572), [`ui/dr-ui/ui/presets.slint:45`](../../ui/dr-ui/ui/presets.slint#L45), [`ui/dr-ui/ui/settings.slint:143`](../../ui/dr-ui/ui/settings.slint#L143), [`ui/dr-ui/ui/widgets.slint:1117`](../../ui/dr-ui/ui/widgets.slint#L1117) | | FR-UI-3 | [`ui/dr-ui/src/collections_ui/controller.rs:143`](../../ui/dr-ui/src/collections_ui/controller.rs#L143), [`ui/dr-ui/src/collections_ui/controller.rs:348`](../../ui/dr-ui/src/collections_ui/controller.rs#L348), [`ui/dr-ui/src/collections_ui/controller.rs:361`](../../ui/dr-ui/src/collections_ui/controller.rs#L361), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/develop/masks.rs:361`](../../ui/dr-ui/src/develop/masks.rs#L361), [`ui/dr-ui/src/develop/repairs.rs:49`](../../ui/dr-ui/src/develop/repairs.rs#L49), [`ui/dr-ui/src/library_ui/grid.rs:228`](../../ui/dr-ui/src/library_ui/grid.rs#L228), [`ui/dr-ui/src/masks_ui.rs:1700`](../../ui/dr-ui/src/masks_ui.rs#L1700), [`ui/dr-ui/src/masks_ui.rs:1722`](../../ui/dr-ui/src/masks_ui.rs#L1722), [`ui/dr-ui/src/masks_ui.rs:339`](../../ui/dr-ui/src/masks_ui.rs#L339), [`ui/dr-ui/src/spots_ui.rs:19`](../../ui/dr-ui/src/spots_ui.rs#L19), [`ui/dr-ui/ui/app.slint:2301`](../../ui/dr-ui/ui/app.slint#L2301), [`ui/dr-ui/ui/collections.slint:1228`](../../ui/dr-ui/ui/collections.slint#L1228), [`ui/dr-ui/ui/collections.slint:4`](../../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/collections.slint:78`](../../ui/dr-ui/ui/collections.slint#L78), [`ui/dr-ui/ui/collections.slint:978`](../../ui/dr-ui/ui/collections.slint#L978), [`ui/dr-ui/ui/masks.slint:1246`](../../ui/dr-ui/ui/masks.slint#L1246), [`ui/dr-ui/ui/widgets.slint:72`](../../ui/dr-ui/ui/widgets.slint#L72) | -| FR-UI-4 | [`tools/traceability/src/gestures.rs:1`](../../tools/traceability/src/gestures.rs#L1), [`tools/traceability/src/keymap.rs:1`](../../tools/traceability/src/keymap.rs#L1), [`ui/dr-ui/src/collections_ui/controller.rs:143`](../../ui/dr-ui/src/collections_ui/controller.rs#L143), [`ui/dr-ui/src/collections_ui/controller.rs:348`](../../ui/dr-ui/src/collections_ui/controller.rs#L348), [`ui/dr-ui/src/collections_ui/controller.rs:361`](../../ui/dr-ui/src/collections_ui/controller.rs#L361), [`ui/dr-ui/src/collections_ui/controller.rs:45`](../../ui/dr-ui/src/collections_ui/controller.rs#L45), [`ui/dr-ui/src/collections_ui/controller.rs:46`](../../ui/dr-ui/src/collections_ui/controller.rs#L46), [`ui/dr-ui/src/collections_ui/controller.rs:55`](../../ui/dr-ui/src/collections_ui/controller.rs#L55), [`ui/dr-ui/src/collections_ui/controller.rs:83`](../../ui/dr-ui/src/collections_ui/controller.rs#L83), [`ui/dr-ui/src/collections_ui/drag.rs:246`](../../ui/dr-ui/src/collections_ui/drag.rs#L246), [`ui/dr-ui/src/collections_ui/drag.rs:256`](../../ui/dr-ui/src/collections_ui/drag.rs#L256), [`ui/dr-ui/src/collections_ui/press.rs:258`](../../ui/dr-ui/src/collections_ui/press.rs#L258), [`ui/dr-ui/src/collections_ui/press.rs:278`](../../ui/dr-ui/src/collections_ui/press.rs#L278), [`ui/dr-ui/src/collections_ui/press.rs:453`](../../ui/dr-ui/src/collections_ui/press.rs#L453), [`ui/dr-ui/src/collections_ui/press.rs:490`](../../ui/dr-ui/src/collections_ui/press.rs#L490), [`ui/dr-ui/src/collections_ui/press.rs:54`](../../ui/dr-ui/src/collections_ui/press.rs#L54), [`ui/dr-ui/src/collections_ui/tree_sync.rs:344`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L344), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:121`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L121), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:138`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L138), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:264`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L264), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:415`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L415), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:444`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L444), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:577`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L577), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:344`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L344), [`ui/dr-ui/src/develop/framing.rs:257`](../../ui/dr-ui/src/develop/framing.rs#L257), [`ui/dr-ui/src/develop/framing.rs:594`](../../ui/dr-ui/src/develop/framing.rs#L594), [`ui/dr-ui/src/develop/framing.rs:619`](../../ui/dr-ui/src/develop/framing.rs#L619), [`ui/dr-ui/src/develop/framing.rs:630`](../../ui/dr-ui/src/develop/framing.rs#L630), [`ui/dr-ui/src/develop/framing.rs:644`](../../ui/dr-ui/src/develop/framing.rs#L644), [`ui/dr-ui/src/develop/framing.rs:818`](../../ui/dr-ui/src/develop/framing.rs#L818), [`ui/dr-ui/src/develop/framing.rs:849`](../../ui/dr-ui/src/develop/framing.rs#L849), [`ui/dr-ui/src/develop/framing.rs:870`](../../ui/dr-ui/src/develop/framing.rs#L870), [`ui/dr-ui/src/develop/framing.rs:995`](../../ui/dr-ui/src/develop/framing.rs#L995), [`ui/dr-ui/src/develop/render.rs:1111`](../../ui/dr-ui/src/develop/render.rs#L1111), [`ui/dr-ui/src/develop/render.rs:1136`](../../ui/dr-ui/src/develop/render.rs#L1136), [`ui/dr-ui/src/develop/render.rs:1159`](../../ui/dr-ui/src/develop/render.rs#L1159), [`ui/dr-ui/src/develop/render.rs:1198`](../../ui/dr-ui/src/develop/render.rs#L1198), [`ui/dr-ui/src/develop/render.rs:47`](../../ui/dr-ui/src/develop/render.rs#L47), [`ui/dr-ui/src/develop/render.rs:66`](../../ui/dr-ui/src/develop/render.rs#L66), [`ui/dr-ui/src/develop/render.rs:79`](../../ui/dr-ui/src/develop/render.rs#L79), [`ui/dr-ui/src/develop_ui.rs:912`](../../ui/dr-ui/src/develop_ui.rs#L912), [`ui/dr-ui/src/duplicates_ui.rs:1`](../../ui/dr-ui/src/duplicates_ui.rs#L1), [`ui/dr-ui/src/gesture_book.rs:3`](../../ui/dr-ui/src/gesture_book.rs#L3), [`ui/dr-ui/src/gestures.rs:127`](../../ui/dr-ui/src/gestures.rs#L127), [`ui/dr-ui/src/gestures.rs:139`](../../ui/dr-ui/src/gestures.rs#L139), [`ui/dr-ui/src/gestures.rs:1`](../../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:1303`](../../ui/dr-ui/src/lib.rs#L1303), [`ui/dr-ui/src/lib.rs:1600`](../../ui/dr-ui/src/lib.rs#L1600), [`ui/dr-ui/src/lib.rs:2522`](../../ui/dr-ui/src/lib.rs#L2522), [`ui/dr-ui/src/lib.rs:2807`](../../ui/dr-ui/src/lib.rs#L2807), [`ui/dr-ui/src/lib.rs:2867`](../../ui/dr-ui/src/lib.rs#L2867), [`ui/dr-ui/src/lib.rs:3026`](../../ui/dr-ui/src/lib.rs#L3026), [`ui/dr-ui/src/lib.rs:3428`](../../ui/dr-ui/src/lib.rs#L3428), [`ui/dr-ui/src/lib.rs:3472`](../../ui/dr-ui/src/lib.rs#L3472), [`ui/dr-ui/src/lib.rs:498`](../../ui/dr-ui/src/lib.rs#L498), [`ui/dr-ui/src/lib.rs:527`](../../ui/dr-ui/src/lib.rs#L527), [`ui/dr-ui/src/library/thumbnails_fetch.rs:760`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L760), [`ui/dr-ui/src/library/thumbnails_fetch.rs:775`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L775), [`ui/dr-ui/src/library_ui/controller.rs:403`](../../ui/dr-ui/src/library_ui/controller.rs#L403), [`ui/dr-ui/src/library_ui/controller.rs:546`](../../ui/dr-ui/src/library_ui/controller.rs#L546), [`ui/dr-ui/src/library_ui/controller.rs:651`](../../ui/dr-ui/src/library_ui/controller.rs#L651), [`ui/dr-ui/src/library_ui/filter_bar.rs:500`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L500), [`ui/dr-ui/src/library_ui/grid.rs:228`](../../ui/dr-ui/src/library_ui/grid.rs#L228), [`ui/dr-ui/src/library_ui/grid.rs:252`](../../ui/dr-ui/src/library_ui/grid.rs#L252), [`ui/dr-ui/src/library_ui/grid.rs:273`](../../ui/dr-ui/src/library_ui/grid.rs#L273), [`ui/dr-ui/src/library_ui/grid.rs:347`](../../ui/dr-ui/src/library_ui/grid.rs#L347), [`ui/dr-ui/src/library_ui/grid.rs:490`](../../ui/dr-ui/src/library_ui/grid.rs#L490), [`ui/dr-ui/src/library_ui/grid.rs:520`](../../ui/dr-ui/src/library_ui/grid.rs#L520), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1178`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1178), [`ui/dr-ui/src/manual.rs:1`](../../ui/dr-ui/src/manual.rs#L1), [`ui/dr-ui/src/settings_ui.rs:121`](../../ui/dr-ui/src/settings_ui.rs#L121), [`ui/dr-ui/src/settings_ui.rs:508`](../../ui/dr-ui/src/settings_ui.rs#L508), [`ui/dr-ui/ui/app.slint:1822`](../../ui/dr-ui/ui/app.slint#L1822), [`ui/dr-ui/ui/app.slint:1989`](../../ui/dr-ui/ui/app.slint#L1989), [`ui/dr-ui/ui/app.slint:2115`](../../ui/dr-ui/ui/app.slint#L2115), [`ui/dr-ui/ui/app.slint:2401`](../../ui/dr-ui/ui/app.slint#L2401), [`ui/dr-ui/ui/app.slint:2563`](../../ui/dr-ui/ui/app.slint#L2563), [`ui/dr-ui/ui/app.slint:2593`](../../ui/dr-ui/ui/app.slint#L2593), [`ui/dr-ui/ui/app.slint:264`](../../ui/dr-ui/ui/app.slint#L264), [`ui/dr-ui/ui/app.slint:2738`](../../ui/dr-ui/ui/app.slint#L2738), [`ui/dr-ui/ui/app.slint:2938`](../../ui/dr-ui/ui/app.slint#L2938), [`ui/dr-ui/ui/app.slint:3494`](../../ui/dr-ui/ui/app.slint#L3494), [`ui/dr-ui/ui/app.slint:3521`](../../ui/dr-ui/ui/app.slint#L3521), [`ui/dr-ui/ui/app.slint:698`](../../ui/dr-ui/ui/app.slint#L698), [`ui/dr-ui/ui/collections.slint:1354`](../../ui/dr-ui/ui/collections.slint#L1354), [`ui/dr-ui/ui/collections.slint:78`](../../ui/dr-ui/ui/collections.slint#L78), [`ui/dr-ui/ui/develop.slint:142`](../../ui/dr-ui/ui/develop.slint#L142), [`ui/dr-ui/ui/develop.slint:328`](../../ui/dr-ui/ui/develop.slint#L328), [`ui/dr-ui/ui/develop.slint:66`](../../ui/dr-ui/ui/develop.slint#L66), [`ui/dr-ui/ui/duplicates.slint:1`](../../ui/dr-ui/ui/duplicates.slint#L1), [`ui/dr-ui/ui/gestures.slint:1`](../../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/icons.slint:367`](../../ui/dr-ui/ui/icons.slint#L367), [`ui/dr-ui/ui/labels.slint:74`](../../ui/dr-ui/ui/labels.slint#L74), [`ui/dr-ui/ui/library.slint:1334`](../../ui/dr-ui/ui/library.slint#L1334), [`ui/dr-ui/ui/library.slint:1361`](../../ui/dr-ui/ui/library.slint#L1361), [`ui/dr-ui/ui/library.slint:1367`](../../ui/dr-ui/ui/library.slint#L1367), [`ui/dr-ui/ui/library.slint:1422`](../../ui/dr-ui/ui/library.slint#L1422), [`ui/dr-ui/ui/library.slint:1617`](../../ui/dr-ui/ui/library.slint#L1617), [`ui/dr-ui/ui/library.slint:1668`](../../ui/dr-ui/ui/library.slint#L1668), [`ui/dr-ui/ui/library.slint:1691`](../../ui/dr-ui/ui/library.slint#L1691), [`ui/dr-ui/ui/library.slint:1698`](../../ui/dr-ui/ui/library.slint#L1698), [`ui/dr-ui/ui/library.slint:1734`](../../ui/dr-ui/ui/library.slint#L1734), [`ui/dr-ui/ui/library.slint:1792`](../../ui/dr-ui/ui/library.slint#L1792), [`ui/dr-ui/ui/library.slint:1799`](../../ui/dr-ui/ui/library.slint#L1799), [`ui/dr-ui/ui/library.slint:3135`](../../ui/dr-ui/ui/library.slint#L3135), [`ui/dr-ui/ui/library.slint:3240`](../../ui/dr-ui/ui/library.slint#L3240), [`ui/dr-ui/ui/library.slint:3391`](../../ui/dr-ui/ui/library.slint#L3391), [`ui/dr-ui/ui/library.slint:5038`](../../ui/dr-ui/ui/library.slint#L5038), [`ui/dr-ui/ui/library.slint:5076`](../../ui/dr-ui/ui/library.slint#L5076), [`ui/dr-ui/ui/library.slint:5180`](../../ui/dr-ui/ui/library.slint#L5180), [`ui/dr-ui/ui/library.slint:567`](../../ui/dr-ui/ui/library.slint#L567), [`ui/dr-ui/ui/library.slint:577`](../../ui/dr-ui/ui/library.slint#L577), [`ui/dr-ui/ui/library.slint:671`](../../ui/dr-ui/ui/library.slint#L671), [`ui/dr-ui/ui/library.slint:740`](../../ui/dr-ui/ui/library.slint#L740), [`ui/dr-ui/ui/settings.slint:121`](../../ui/dr-ui/ui/settings.slint#L121), [`ui/dr-ui/ui/settings.slint:172`](../../ui/dr-ui/ui/settings.slint#L172), [`ui/dr-ui/ui/settings.slint:635`](../../ui/dr-ui/ui/settings.slint#L635) | +| FR-UI-4 | [`tools/traceability/src/gestures.rs:1`](../../tools/traceability/src/gestures.rs#L1), [`tools/traceability/src/keymap.rs:1`](../../tools/traceability/src/keymap.rs#L1), [`ui/dr-ui/src/collections_ui/controller.rs:143`](../../ui/dr-ui/src/collections_ui/controller.rs#L143), [`ui/dr-ui/src/collections_ui/controller.rs:348`](../../ui/dr-ui/src/collections_ui/controller.rs#L348), [`ui/dr-ui/src/collections_ui/controller.rs:361`](../../ui/dr-ui/src/collections_ui/controller.rs#L361), [`ui/dr-ui/src/collections_ui/controller.rs:45`](../../ui/dr-ui/src/collections_ui/controller.rs#L45), [`ui/dr-ui/src/collections_ui/controller.rs:46`](../../ui/dr-ui/src/collections_ui/controller.rs#L46), [`ui/dr-ui/src/collections_ui/controller.rs:55`](../../ui/dr-ui/src/collections_ui/controller.rs#L55), [`ui/dr-ui/src/collections_ui/controller.rs:83`](../../ui/dr-ui/src/collections_ui/controller.rs#L83), [`ui/dr-ui/src/collections_ui/drag.rs:246`](../../ui/dr-ui/src/collections_ui/drag.rs#L246), [`ui/dr-ui/src/collections_ui/drag.rs:256`](../../ui/dr-ui/src/collections_ui/drag.rs#L256), [`ui/dr-ui/src/collections_ui/press.rs:258`](../../ui/dr-ui/src/collections_ui/press.rs#L258), [`ui/dr-ui/src/collections_ui/press.rs:278`](../../ui/dr-ui/src/collections_ui/press.rs#L278), [`ui/dr-ui/src/collections_ui/press.rs:453`](../../ui/dr-ui/src/collections_ui/press.rs#L453), [`ui/dr-ui/src/collections_ui/press.rs:490`](../../ui/dr-ui/src/collections_ui/press.rs#L490), [`ui/dr-ui/src/collections_ui/press.rs:54`](../../ui/dr-ui/src/collections_ui/press.rs#L54), [`ui/dr-ui/src/collections_ui/tree_sync.rs:344`](../../ui/dr-ui/src/collections_ui/tree_sync.rs#L344), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:121`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L121), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:138`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L138), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:264`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L264), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:415`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L415), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:444`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L444), [`ui/dr-ui/src/collections_ui/wiring_grid.rs:577`](../../ui/dr-ui/src/collections_ui/wiring_grid.rs#L577), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:287`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L287), [`ui/dr-ui/src/collections_ui/wiring_tree.rs:344`](../../ui/dr-ui/src/collections_ui/wiring_tree.rs#L344), [`ui/dr-ui/src/develop/framing.rs:257`](../../ui/dr-ui/src/develop/framing.rs#L257), [`ui/dr-ui/src/develop/framing.rs:594`](../../ui/dr-ui/src/develop/framing.rs#L594), [`ui/dr-ui/src/develop/framing.rs:619`](../../ui/dr-ui/src/develop/framing.rs#L619), [`ui/dr-ui/src/develop/framing.rs:630`](../../ui/dr-ui/src/develop/framing.rs#L630), [`ui/dr-ui/src/develop/framing.rs:644`](../../ui/dr-ui/src/develop/framing.rs#L644), [`ui/dr-ui/src/develop/framing.rs:818`](../../ui/dr-ui/src/develop/framing.rs#L818), [`ui/dr-ui/src/develop/framing.rs:849`](../../ui/dr-ui/src/develop/framing.rs#L849), [`ui/dr-ui/src/develop/framing.rs:870`](../../ui/dr-ui/src/develop/framing.rs#L870), [`ui/dr-ui/src/develop/framing.rs:995`](../../ui/dr-ui/src/develop/framing.rs#L995), [`ui/dr-ui/src/develop/render.rs:1102`](../../ui/dr-ui/src/develop/render.rs#L1102), [`ui/dr-ui/src/develop/render.rs:1127`](../../ui/dr-ui/src/develop/render.rs#L1127), [`ui/dr-ui/src/develop/render.rs:1150`](../../ui/dr-ui/src/develop/render.rs#L1150), [`ui/dr-ui/src/develop/render.rs:1189`](../../ui/dr-ui/src/develop/render.rs#L1189), [`ui/dr-ui/src/develop/render.rs:47`](../../ui/dr-ui/src/develop/render.rs#L47), [`ui/dr-ui/src/develop/render.rs:66`](../../ui/dr-ui/src/develop/render.rs#L66), [`ui/dr-ui/src/develop/render.rs:79`](../../ui/dr-ui/src/develop/render.rs#L79), [`ui/dr-ui/src/develop_ui.rs:912`](../../ui/dr-ui/src/develop_ui.rs#L912), [`ui/dr-ui/src/duplicates_ui.rs:1`](../../ui/dr-ui/src/duplicates_ui.rs#L1), [`ui/dr-ui/src/gesture_book.rs:3`](../../ui/dr-ui/src/gesture_book.rs#L3), [`ui/dr-ui/src/gestures.rs:127`](../../ui/dr-ui/src/gestures.rs#L127), [`ui/dr-ui/src/gestures.rs:139`](../../ui/dr-ui/src/gestures.rs#L139), [`ui/dr-ui/src/gestures.rs:1`](../../ui/dr-ui/src/gestures.rs#L1), [`ui/dr-ui/src/lib.rs:1303`](../../ui/dr-ui/src/lib.rs#L1303), [`ui/dr-ui/src/lib.rs:1600`](../../ui/dr-ui/src/lib.rs#L1600), [`ui/dr-ui/src/lib.rs:2522`](../../ui/dr-ui/src/lib.rs#L2522), [`ui/dr-ui/src/lib.rs:2807`](../../ui/dr-ui/src/lib.rs#L2807), [`ui/dr-ui/src/lib.rs:2867`](../../ui/dr-ui/src/lib.rs#L2867), [`ui/dr-ui/src/lib.rs:3026`](../../ui/dr-ui/src/lib.rs#L3026), [`ui/dr-ui/src/lib.rs:3428`](../../ui/dr-ui/src/lib.rs#L3428), [`ui/dr-ui/src/lib.rs:3472`](../../ui/dr-ui/src/lib.rs#L3472), [`ui/dr-ui/src/lib.rs:498`](../../ui/dr-ui/src/lib.rs#L498), [`ui/dr-ui/src/lib.rs:527`](../../ui/dr-ui/src/lib.rs#L527), [`ui/dr-ui/src/library/thumbnails_fetch.rs:760`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L760), [`ui/dr-ui/src/library/thumbnails_fetch.rs:775`](../../ui/dr-ui/src/library/thumbnails_fetch.rs#L775), [`ui/dr-ui/src/library_ui/controller.rs:403`](../../ui/dr-ui/src/library_ui/controller.rs#L403), [`ui/dr-ui/src/library_ui/controller.rs:546`](../../ui/dr-ui/src/library_ui/controller.rs#L546), [`ui/dr-ui/src/library_ui/controller.rs:651`](../../ui/dr-ui/src/library_ui/controller.rs#L651), [`ui/dr-ui/src/library_ui/filter_bar.rs:500`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L500), [`ui/dr-ui/src/library_ui/grid.rs:228`](../../ui/dr-ui/src/library_ui/grid.rs#L228), [`ui/dr-ui/src/library_ui/grid.rs:252`](../../ui/dr-ui/src/library_ui/grid.rs#L252), [`ui/dr-ui/src/library_ui/grid.rs:273`](../../ui/dr-ui/src/library_ui/grid.rs#L273), [`ui/dr-ui/src/library_ui/grid.rs:347`](../../ui/dr-ui/src/library_ui/grid.rs#L347), [`ui/dr-ui/src/library_ui/grid.rs:490`](../../ui/dr-ui/src/library_ui/grid.rs#L490), [`ui/dr-ui/src/library_ui/grid.rs:520`](../../ui/dr-ui/src/library_ui/grid.rs#L520), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1178`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1178), [`ui/dr-ui/src/manual.rs:1`](../../ui/dr-ui/src/manual.rs#L1), [`ui/dr-ui/src/settings_ui.rs:121`](../../ui/dr-ui/src/settings_ui.rs#L121), [`ui/dr-ui/src/settings_ui.rs:508`](../../ui/dr-ui/src/settings_ui.rs#L508), [`ui/dr-ui/ui/app.slint:1822`](../../ui/dr-ui/ui/app.slint#L1822), [`ui/dr-ui/ui/app.slint:1989`](../../ui/dr-ui/ui/app.slint#L1989), [`ui/dr-ui/ui/app.slint:2115`](../../ui/dr-ui/ui/app.slint#L2115), [`ui/dr-ui/ui/app.slint:2401`](../../ui/dr-ui/ui/app.slint#L2401), [`ui/dr-ui/ui/app.slint:2563`](../../ui/dr-ui/ui/app.slint#L2563), [`ui/dr-ui/ui/app.slint:2593`](../../ui/dr-ui/ui/app.slint#L2593), [`ui/dr-ui/ui/app.slint:264`](../../ui/dr-ui/ui/app.slint#L264), [`ui/dr-ui/ui/app.slint:2738`](../../ui/dr-ui/ui/app.slint#L2738), [`ui/dr-ui/ui/app.slint:2938`](../../ui/dr-ui/ui/app.slint#L2938), [`ui/dr-ui/ui/app.slint:3494`](../../ui/dr-ui/ui/app.slint#L3494), [`ui/dr-ui/ui/app.slint:3521`](../../ui/dr-ui/ui/app.slint#L3521), [`ui/dr-ui/ui/app.slint:698`](../../ui/dr-ui/ui/app.slint#L698), [`ui/dr-ui/ui/collections.slint:1354`](../../ui/dr-ui/ui/collections.slint#L1354), [`ui/dr-ui/ui/collections.slint:78`](../../ui/dr-ui/ui/collections.slint#L78), [`ui/dr-ui/ui/develop.slint:142`](../../ui/dr-ui/ui/develop.slint#L142), [`ui/dr-ui/ui/develop.slint:328`](../../ui/dr-ui/ui/develop.slint#L328), [`ui/dr-ui/ui/develop.slint:66`](../../ui/dr-ui/ui/develop.slint#L66), [`ui/dr-ui/ui/duplicates.slint:1`](../../ui/dr-ui/ui/duplicates.slint#L1), [`ui/dr-ui/ui/gestures.slint:1`](../../ui/dr-ui/ui/gestures.slint#L1), [`ui/dr-ui/ui/icons.slint:367`](../../ui/dr-ui/ui/icons.slint#L367), [`ui/dr-ui/ui/labels.slint:74`](../../ui/dr-ui/ui/labels.slint#L74), [`ui/dr-ui/ui/library.slint:1334`](../../ui/dr-ui/ui/library.slint#L1334), [`ui/dr-ui/ui/library.slint:1361`](../../ui/dr-ui/ui/library.slint#L1361), [`ui/dr-ui/ui/library.slint:1367`](../../ui/dr-ui/ui/library.slint#L1367), [`ui/dr-ui/ui/library.slint:1422`](../../ui/dr-ui/ui/library.slint#L1422), [`ui/dr-ui/ui/library.slint:1617`](../../ui/dr-ui/ui/library.slint#L1617), [`ui/dr-ui/ui/library.slint:1668`](../../ui/dr-ui/ui/library.slint#L1668), [`ui/dr-ui/ui/library.slint:1691`](../../ui/dr-ui/ui/library.slint#L1691), [`ui/dr-ui/ui/library.slint:1698`](../../ui/dr-ui/ui/library.slint#L1698), [`ui/dr-ui/ui/library.slint:1734`](../../ui/dr-ui/ui/library.slint#L1734), [`ui/dr-ui/ui/library.slint:1792`](../../ui/dr-ui/ui/library.slint#L1792), [`ui/dr-ui/ui/library.slint:1799`](../../ui/dr-ui/ui/library.slint#L1799), [`ui/dr-ui/ui/library.slint:3135`](../../ui/dr-ui/ui/library.slint#L3135), [`ui/dr-ui/ui/library.slint:3240`](../../ui/dr-ui/ui/library.slint#L3240), [`ui/dr-ui/ui/library.slint:3391`](../../ui/dr-ui/ui/library.slint#L3391), [`ui/dr-ui/ui/library.slint:5038`](../../ui/dr-ui/ui/library.slint#L5038), [`ui/dr-ui/ui/library.slint:5076`](../../ui/dr-ui/ui/library.slint#L5076), [`ui/dr-ui/ui/library.slint:5180`](../../ui/dr-ui/ui/library.slint#L5180), [`ui/dr-ui/ui/library.slint:567`](../../ui/dr-ui/ui/library.slint#L567), [`ui/dr-ui/ui/library.slint:577`](../../ui/dr-ui/ui/library.slint#L577), [`ui/dr-ui/ui/library.slint:671`](../../ui/dr-ui/ui/library.slint#L671), [`ui/dr-ui/ui/library.slint:740`](../../ui/dr-ui/ui/library.slint#L740), [`ui/dr-ui/ui/settings.slint:121`](../../ui/dr-ui/ui/settings.slint#L121), [`ui/dr-ui/ui/settings.slint:172`](../../ui/dr-ui/ui/settings.slint#L172), [`ui/dr-ui/ui/settings.slint:635`](../../ui/dr-ui/ui/settings.slint#L635) | | FR-UI-5 | [`core/dr-types/src/place.rs:118`](../../core/dr-types/src/place.rs#L118), [`tools/traceability/src/chord.rs:1`](../../tools/traceability/src/chord.rs#L1), [`tools/traceability/src/keymap.rs:1`](../../tools/traceability/src/keymap.rs#L1), [`ui/dr-ui/src/collections_ui/mod.rs:1`](../../ui/dr-ui/src/collections_ui/mod.rs#L1), [`ui/dr-ui/src/develop_ui.rs:957`](../../ui/dr-ui/src/develop_ui.rs#L957), [`ui/dr-ui/src/gestures.rs:139`](../../ui/dr-ui/src/gestures.rs#L139), [`ui/dr-ui/src/identity_ui.rs:1643`](../../ui/dr-ui/src/identity_ui.rs#L1643), [`ui/dr-ui/src/identity_ui.rs:802`](../../ui/dr-ui/src/identity_ui.rs#L802), [`ui/dr-ui/src/lib.rs:3410`](../../ui/dr-ui/src/lib.rs#L3410), [`ui/dr-ui/src/lib.rs:3428`](../../ui/dr-ui/src/lib.rs#L3428), [`ui/dr-ui/src/lib.rs:3442`](../../ui/dr-ui/src/lib.rs#L3442), [`ui/dr-ui/src/lib.rs:3623`](../../ui/dr-ui/src/lib.rs#L3623), [`ui/dr-ui/src/library/filters.rs:79`](../../ui/dr-ui/src/library/filters.rs#L79), [`ui/dr-ui/src/library_ui/filter_bar.rs:57`](../../ui/dr-ui/src/library_ui/filter_bar.rs#L57), [`ui/dr-ui/src/library_ui/grid.rs:367`](../../ui/dr-ui/src/library_ui/grid.rs#L367), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1035`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1035), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1154`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1154), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1215`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1215), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1285`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1285), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:1311`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L1311), [`ui/dr-ui/src/library_ui/ratings_keywords.rs:464`](../../ui/dr-ui/src/library_ui/ratings_keywords.rs#L464), [`ui/dr-ui/src/masks_ui.rs:1655`](../../ui/dr-ui/src/masks_ui.rs#L1655), [`ui/dr-ui/src/place.rs:331`](../../ui/dr-ui/src/place.rs#L331), [`ui/dr-ui/src/settings_ui.rs:394`](../../ui/dr-ui/src/settings_ui.rs#L394), [`ui/dr-ui/ui/app.slint:1090`](../../ui/dr-ui/ui/app.slint#L1090), [`ui/dr-ui/ui/app.slint:1675`](../../ui/dr-ui/ui/app.slint#L1675), [`ui/dr-ui/ui/app.slint:2401`](../../ui/dr-ui/ui/app.slint#L2401), [`ui/dr-ui/ui/app.slint:2551`](../../ui/dr-ui/ui/app.slint#L2551), [`ui/dr-ui/ui/app.slint:2693`](../../ui/dr-ui/ui/app.slint#L2693), [`ui/dr-ui/ui/app.slint:2738`](../../ui/dr-ui/ui/app.slint#L2738), [`ui/dr-ui/ui/app.slint:2791`](../../ui/dr-ui/ui/app.slint#L2791), [`ui/dr-ui/ui/app.slint:2822`](../../ui/dr-ui/ui/app.slint#L2822), [`ui/dr-ui/ui/app.slint:3459`](../../ui/dr-ui/ui/app.slint#L3459), [`ui/dr-ui/ui/app.slint:3478`](../../ui/dr-ui/ui/app.slint#L3478), [`ui/dr-ui/ui/app.slint:424`](../../ui/dr-ui/ui/app.slint#L424), [`ui/dr-ui/ui/app.slint:687`](../../ui/dr-ui/ui/app.slint#L687), [`ui/dr-ui/ui/app.slint:694`](../../ui/dr-ui/ui/app.slint#L694), [`ui/dr-ui/ui/app.slint:698`](../../ui/dr-ui/ui/app.slint#L698), [`ui/dr-ui/ui/app.slint:704`](../../ui/dr-ui/ui/app.slint#L704), [`ui/dr-ui/ui/app.slint:760`](../../ui/dr-ui/ui/app.slint#L760), [`ui/dr-ui/ui/collections.slint:111`](../../ui/dr-ui/ui/collections.slint#L111), [`ui/dr-ui/ui/collections.slint:4`](../../ui/dr-ui/ui/collections.slint#L4), [`ui/dr-ui/ui/develop.slint:168`](../../ui/dr-ui/ui/develop.slint#L168), [`ui/dr-ui/ui/develop.slint:55`](../../ui/dr-ui/ui/develop.slint#L55), [`ui/dr-ui/ui/export.slint:1`](../../ui/dr-ui/ui/export.slint#L1), [`ui/dr-ui/ui/export.slint:246`](../../ui/dr-ui/ui/export.slint#L246), [`ui/dr-ui/ui/identity.slint:294`](../../ui/dr-ui/ui/identity.slint#L294), [`ui/dr-ui/ui/identity.slint:400`](../../ui/dr-ui/ui/identity.slint#L400), [`ui/dr-ui/ui/keys.slint:1`](../../ui/dr-ui/ui/keys.slint#L1), [`ui/dr-ui/ui/library.slint:1044`](../../ui/dr-ui/ui/library.slint#L1044), [`ui/dr-ui/ui/library.slint:1614`](../../ui/dr-ui/ui/library.slint#L1614), [`ui/dr-ui/ui/library.slint:1623`](../../ui/dr-ui/ui/library.slint#L1623), [`ui/dr-ui/ui/library.slint:1628`](../../ui/dr-ui/ui/library.slint#L1628), [`ui/dr-ui/ui/library.slint:1640`](../../ui/dr-ui/ui/library.slint#L1640), [`ui/dr-ui/ui/library.slint:1888`](../../ui/dr-ui/ui/library.slint#L1888), [`ui/dr-ui/ui/library.slint:2018`](../../ui/dr-ui/ui/library.slint#L2018), [`ui/dr-ui/ui/library.slint:2658`](../../ui/dr-ui/ui/library.slint#L2658), [`ui/dr-ui/ui/library.slint:3101`](../../ui/dr-ui/ui/library.slint#L3101), [`ui/dr-ui/ui/library.slint:3177`](../../ui/dr-ui/ui/library.slint#L3177), [`ui/dr-ui/ui/library.slint:3196`](../../ui/dr-ui/ui/library.slint#L3196), [`ui/dr-ui/ui/library.slint:3202`](../../ui/dr-ui/ui/library.slint#L3202), [`ui/dr-ui/ui/library.slint:3209`](../../ui/dr-ui/ui/library.slint#L3209), [`ui/dr-ui/ui/library.slint:3229`](../../ui/dr-ui/ui/library.slint#L3229), [`ui/dr-ui/ui/library.slint:3240`](../../ui/dr-ui/ui/library.slint#L3240), [`ui/dr-ui/ui/library.slint:3318`](../../ui/dr-ui/ui/library.slint#L3318), [`ui/dr-ui/ui/library.slint:3391`](../../ui/dr-ui/ui/library.slint#L3391), [`ui/dr-ui/ui/library.slint:3998`](../../ui/dr-ui/ui/library.slint#L3998), [`ui/dr-ui/ui/library.slint:5093`](../../ui/dr-ui/ui/library.slint#L5093), [`ui/dr-ui/ui/library.slint:647`](../../ui/dr-ui/ui/library.slint#L647), [`ui/dr-ui/ui/library.slint:665`](../../ui/dr-ui/ui/library.slint#L665), [`ui/dr-ui/ui/library.slint:686`](../../ui/dr-ui/ui/library.slint#L686), [`ui/dr-ui/ui/presets.slint:383`](../../ui/dr-ui/ui/presets.slint#L383), [`ui/dr-ui/ui/session.slint:75`](../../ui/dr-ui/ui/session.slint#L75) | | FR-UI-6 | [`ui/dr-ui/ui/widgets.slint:1`](../../ui/dr-ui/ui/widgets.slint#L1) | | FR-UI-7 | [`core/dr-pipeline/src/descriptor.rs:195`](../../core/dr-pipeline/src/descriptor.rs#L195), [`core/dr-pipeline/src/framing.rs:555`](../../core/dr-pipeline/src/framing.rs#L555), [`core/dr-types/src/settings.rs:492`](../../core/dr-types/src/settings.rs#L492), [`ui/dr-ui/src/develop/rows.rs:118`](../../ui/dr-ui/src/develop/rows.rs#L118), [`ui/dr-ui/src/lib.rs:3235`](../../ui/dr-ui/src/lib.rs#L3235), [`ui/dr-ui/ui/adjust.slint:1000`](../../ui/dr-ui/ui/adjust.slint#L1000), [`ui/dr-ui/ui/app.slint:2239`](../../ui/dr-ui/ui/app.slint#L2239), [`ui/dr-ui/ui/settings.slint:660`](../../ui/dr-ui/ui/settings.slint#L660), [`ui/dr-ui/ui/toolrail.slint:91`](../../ui/dr-ui/ui/toolrail.slint#L91) | @@ -170,9 +170,9 @@ _None._ | NFR-OPS-3 | [`core/dr-types/src/settings.rs:1`](../../core/dr-types/src/settings.rs#L1), [`ui/dr-ui/src/settings_store.rs:1`](../../ui/dr-ui/src/settings_store.rs#L1) | | NFR-P1 | [`core/dr-catalog/src/lib.rs:1`](../../core/dr-catalog/src/lib.rs#L1), [`core/dr-catalog/src/scan.rs:1`](../../core/dr-catalog/src/scan.rs#L1), [`core/dr-catalog/src/walk.rs:161`](../../core/dr-catalog/src/walk.rs#L161), [`core/dr-catalog/src/walk.rs:1`](../../core/dr-catalog/src/walk.rs#L1), [`tools/bench/src/catalog_open.rs:1`](../../tools/bench/src/catalog_open.rs#L1) | | NFR-P13 | [`core/dr-decode/src/preview.rs:121`](../../core/dr-decode/src/preview.rs#L121) | -| NFR-P14 | [`core/dr-gpu/src/focus.rs:186`](../../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`ui/dr-ui/src/develop/render.rs:409`](../../ui/dr-ui/src/develop/render.rs#L409), [`ui/dr-ui/src/lib.rs:2304`](../../ui/dr-ui/src/lib.rs#L2304) | +| NFR-P14 | [`core/dr-gpu/src/focus.rs:186`](../../core/dr-gpu/src/focus.rs#L186), [`core/dr-gpu/src/focus.rs:1`](../../core/dr-gpu/src/focus.rs#L1), [`core/dr-gpu/src/focus.rs:317`](../../core/dr-gpu/src/focus.rs#L317), [`core/dr-gpu/src/shaders/focus_peak.wgsl:1`](../../core/dr-gpu/src/shaders/focus_peak.wgsl#L1), [`ui/dr-ui/src/develop/render.rs:400`](../../ui/dr-ui/src/develop/render.rs#L400), [`ui/dr-ui/src/lib.rs:2304`](../../ui/dr-ui/src/lib.rs#L2304) | | NFR-P3 | [`tools/bench/src/thumbnails.rs:1`](../../tools/bench/src/thumbnails.rs#L1) | -| NFR-P5 | [`core/dr-catalog/src/schema.rs:594`](../../core/dr-catalog/src/schema.rs#L594), [`core/dr-gpu/src/adjust.rs:166`](../../core/dr-gpu/src/adjust.rs#L166), [`core/dr-gpu/src/adjust.rs:2925`](../../core/dr-gpu/src/adjust.rs#L2925), [`core/dr-pipeline/src/detail.rs:1268`](../../core/dr-pipeline/src/detail.rs#L1268), [`core/dr-pipeline/src/detail.rs:667`](../../core/dr-pipeline/src/detail.rs#L667), [`ui/dr-ui/src/library/cells.rs:374`](../../ui/dr-ui/src/library/cells.rs#L374), [`ui/dr-ui/src/library/cells.rs:715`](../../ui/dr-ui/src/library/cells.rs#L715), [`ui/dr-ui/src/library_ui/controller.rs:58`](../../ui/dr-ui/src/library_ui/controller.rs#L58), [`ui/dr-ui/src/library_ui/timeline.rs:382`](../../ui/dr-ui/src/library_ui/timeline.rs#L382) | +| NFR-P5 | [`core/dr-catalog/src/schema.rs:594`](../../core/dr-catalog/src/schema.rs#L594), [`core/dr-gpu/src/adjust.rs:168`](../../core/dr-gpu/src/adjust.rs#L168), [`core/dr-gpu/src/adjust.rs:3017`](../../core/dr-gpu/src/adjust.rs#L3017), [`core/dr-pipeline/src/detail.rs:1149`](../../core/dr-pipeline/src/detail.rs#L1149), [`core/dr-pipeline/src/detail.rs:620`](../../core/dr-pipeline/src/detail.rs#L620), [`ui/dr-ui/src/library/cells.rs:374`](../../ui/dr-ui/src/library/cells.rs#L374), [`ui/dr-ui/src/library/cells.rs:715`](../../ui/dr-ui/src/library/cells.rs#L715), [`ui/dr-ui/src/library_ui/controller.rs:58`](../../ui/dr-ui/src/library_ui/controller.rs#L58), [`ui/dr-ui/src/library_ui/timeline.rs:382`](../../ui/dr-ui/src/library_ui/timeline.rs#L382) | | NFR-P9 | [`core/dr-catalog/src/backfilled.rs:1`](../../core/dr-catalog/src/backfilled.rs#L1), [`core/dr-catalog/src/schema.rs:947`](../../core/dr-catalog/src/schema.rs#L947), [`core/dr-face/src/references.rs:1`](../../core/dr-face/src/references.rs#L1), [`ui/dr-ui/src/collections_ui/mod.rs:1`](../../ui/dr-ui/src/collections_ui/mod.rs#L1), [`ui/dr-ui/src/duplicates.rs:1`](../../ui/dr-ui/src/duplicates.rs#L1), [`ui/dr-ui/src/duplicates_ui.rs:1`](../../ui/dr-ui/src/duplicates_ui.rs#L1), [`ui/dr-ui/src/executors.rs:136`](../../ui/dr-ui/src/executors.rs#L136), [`ui/dr-ui/src/executors.rs:220`](../../ui/dr-ui/src/executors.rs#L220), [`ui/dr-ui/src/export.rs:1122`](../../ui/dr-ui/src/export.rs#L1122), [`ui/dr-ui/src/library/mod.rs:1`](../../ui/dr-ui/src/library/mod.rs#L1), [`ui/dr-ui/src/library_ui/mod.rs:1`](../../ui/dr-ui/src/library_ui/mod.rs#L1), [`ui/dr-ui/src/net_runtime.rs:48`](../../ui/dr-ui/src/net_runtime.rs#L48), [`ui/dr-ui/src/trash.rs:1`](../../ui/dr-ui/src/trash.rs#L1) | | NFR-PORT-1 | [`core/dr-catalog/src/walk.rs:1`](../../core/dr-catalog/src/walk.rs#L1), [`core/dr-types/src/lib.rs:272`](../../core/dr-types/src/lib.rs#L272), [`core/dr-types/src/lib.rs:305`](../../core/dr-types/src/lib.rs#L305), [`platform/dr-plat/src/dirs.rs:1`](../../platform/dr-plat/src/dirs.rs#L1), [`platform/dr-plat/src/display.rs:1`](../../platform/dr-plat/src/display.rs#L1), [`platform/dr-plat/src/storage.rs:1`](../../platform/dr-plat/src/storage.rs#L1), [`platform/dr-plat/src/storage.rs:216`](../../platform/dr-plat/src/storage.rs#L216), [`platform/dr-plat/src/storage.rs:287`](../../platform/dr-plat/src/storage.rs#L287), [`platform/dr-plat/src/storage.rs:344`](../../platform/dr-plat/src/storage.rs#L344), [`platform/dr-plat/src/volumes.rs:1`](../../platform/dr-plat/src/volumes.rs#L1), [`platform/dr-plat/src/volumes.rs:62`](../../platform/dr-plat/src/volumes.rs#L62) | | NFR-PORT-2 | [`core/dr-gpu/src/lib.rs:1`](../../core/dr-gpu/src/lib.rs#L1) | @@ -185,7 +185,7 @@ _None._ | NFR-R6 | [`core/dr-catalog/src/error.rs:1`](../../core/dr-catalog/src/error.rs#L1), [`core/dr-catalog/src/lib.rs:270`](../../core/dr-catalog/src/lib.rs#L270), [`core/dr-catalog/src/recovery.rs:1`](../../core/dr-catalog/src/recovery.rs#L1) | | NFR-R7 | [`core/dr-gpu/src/error.rs:1`](../../core/dr-gpu/src/error.rs#L1) | | NFR-R8 | [`core/dr-gpu/src/error.rs:1`](../../core/dr-gpu/src/error.rs#L1) | -| NFR-RES-1 | [`core/dr-gpu/src/adjust.rs:1314`](../../core/dr-gpu/src/adjust.rs#L1314), [`core/dr-pipeline/src/history.rs:86`](../../core/dr-pipeline/src/history.rs#L86), [`ui/dr-ui/src/develop/render.rs:561`](../../ui/dr-ui/src/develop/render.rs#L561), [`ui/dr-ui/src/identity_ui.rs:125`](../../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:116`](../../ui/dr-ui/src/lib.rs#L116), [`ui/dr-ui/src/memory.rs:1`](../../ui/dr-ui/src/memory.rs#L1) | +| NFR-RES-1 | [`core/dr-gpu/src/adjust.rs:1399`](../../core/dr-gpu/src/adjust.rs#L1399), [`core/dr-pipeline/src/history.rs:86`](../../core/dr-pipeline/src/history.rs#L86), [`ui/dr-ui/src/develop/render.rs:552`](../../ui/dr-ui/src/develop/render.rs#L552), [`ui/dr-ui/src/identity_ui.rs:125`](../../ui/dr-ui/src/identity_ui.rs#L125), [`ui/dr-ui/src/lib.rs:116`](../../ui/dr-ui/src/lib.rs#L116), [`ui/dr-ui/src/memory.rs:1`](../../ui/dr-ui/src/memory.rs#L1) | | NFR-RES-2 | [`ui/dr-ui/src/faces.rs:463`](../../ui/dr-ui/src/faces.rs#L463), [`ui/dr-ui/src/library/sweep.rs:243`](../../ui/dr-ui/src/library/sweep.rs#L243), [`ui/dr-ui/src/repairs.rs:1150`](../../ui/dr-ui/src/repairs.rs#L1150), [`ui/dr-ui/src/repairs.rs:1`](../../ui/dr-ui/src/repairs.rs#L1) | | NFR-RES-4 | [`core/dr-catalog/src/cache.rs:1`](../../core/dr-catalog/src/cache.rs#L1), [`core/dr-catalog/src/face_shard.rs:1`](../../core/dr-catalog/src/face_shard.rs#L1), [`core/dr-catalog/src/schema.rs:1212`](../../core/dr-catalog/src/schema.rs#L1212), [`core/dr-gpu/src/lib.rs:95`](../../core/dr-gpu/src/lib.rs#L95), [`core/dr-thumbs/src/codec.rs:1`](../../core/dr-thumbs/src/codec.rs#L1), [`core/dr-thumbs/src/lib.rs:1`](../../core/dr-thumbs/src/lib.rs#L1), [`core/dr-thumbs/src/lib.rs:393`](../../core/dr-thumbs/src/lib.rs#L393) | | NFR-SEC-1 | [`core/dr-decode/src/error.rs:1`](../../core/dr-decode/src/error.rs#L1), [`core/dr-decode/src/error.rs:30`](../../core/dr-decode/src/error.rs#L30) | diff --git a/ui/dr-ui/src/develop/render.rs b/ui/dr-ui/src/develop/render.rs index a261af4..86c7dcb 100644 --- a/ui/dr-ui/src/develop/render.rs +++ b/ui/dr-ui/src/develop/render.rs @@ -139,17 +139,15 @@ impl DevelopSession { /// almost every edit, so this costs nothing to the frames that do not /// need it. /// - /// `space` has to be the space `shader` was composed for. It is the last - /// pass of the detail chain that performs the output transform when there - /// is one, so the two would otherwise be free to disagree about which - /// primaries the file is in — and the result would be a correctly - /// labelled file with the wrong colours in it (FR-EXP-2). + /// The output space is `shader`'s alone: since D19 no detail pass encodes, + /// and the view pass `shader` carries performs the output transform, so + /// the two halves cannot disagree about which primaries the file is in + /// (FR-EXP-2). pub(super) fn render_with_masks( &mut self, shader: &dr_pipeline::operation::ComposedShader, w: u32, h: u32, - space: dr_types::ColourSpace, ) -> Result<(), String> { let ctx = self.ctx.clone(); self.ensure_subject_fields(&ctx); @@ -173,9 +171,7 @@ impl DevelopSession { // Empty for every edit with no active neighbourhood operation — which // is almost all of them — and `render_detailed` then falls straight // through to the single masked dispatch this used to call. - let detail = self - .graph - .compose_detail_for(self.demosaiced.size(), (w, h), space); + let detail = self.graph.compose_detail(self.demosaiced.size(), (w, h)); // Detail passes read what the colour pass wrote, so the key they are // cached against is the colour key: moving a sharpening slider re-runs // this stage and not the fused one (FR-DEV-3d). @@ -266,12 +262,7 @@ impl DevelopSession { // Rasterise the masks first: the shader addresses array slices by // index, so the array has to describe *this* stack before it is bound. - // - // The same `space` to both, necessarily: where a detail stage exists - // it is the *last* pass that performs the output transform, and two - // halves composed for different spaces would encode the frame twice - // or not at all. - self.render_with_masks(&shader, w, h, space)?; + self.render_with_masks(&shader, w, h)?; let texture = self.adjust.output().ok_or("nothing was rendered")?; // The import is fallible on format and usage only, and both are fixed @@ -658,7 +649,7 @@ impl DevelopSession { // uniform baked at composition, so composing before this point would // restore the framing and export the zoom anyway. let shader = self.graph.compose_for(space); - let rendered = self.render_with_masks(&shader, w, h, space); + let rendered = self.render_with_masks(&shader, w, h); self.graph.framing_mut().set_view(saved_view); rendered?;