use internal::{RenderPipelineShared, RunInOutStage, RunInPlaceStage};
use std::any::Any;
use crate::{
api::JxlOutputBuffer,
error::Result,
image::{Image, ImageDataType},
render::buffer_splitter::BufferSplitter,
};
pub mod buffer_splitter;
mod builder;
mod channels;
mod internal;
pub mod low_memory_pipeline;
pub mod save;
mod simd_utils;
#[cfg(test)]
mod simple_pipeline;
pub mod stages;
#[cfg(test)]
mod test;
const MAX_BORDER: usize = 9;
pub(crate) use builder::RenderPipelineBuilder;
pub(crate) use channels::{Channels, ChannelsMut};
pub(crate) use low_memory_pipeline::LowMemoryRenderPipeline;
#[cfg(test)]
pub(crate) use simple_pipeline::SimpleRenderPipeline;
pub enum StageSpecialCase {
F32ToU8 { channel: usize, bit_depth: u8 },
ModularToF32 { channel: usize, bit_depth: u8 },
}
pub trait RenderPipelineInPlaceStage: Any + std::fmt::Display + Send + Sync {
type Type: ImageDataType;
fn process_row_chunk(
&self,
position: (usize, usize),
xsize: usize,
row: &mut [&mut [Self::Type]],
state: Option<&mut (dyn Any + Send)>,
);
fn init_local_state(&self, _thread_index: usize) -> Result<Option<Box<dyn Any + Send>>> {
Ok(None)
}
fn uses_channel(&self, c: usize) -> bool;
fn is_special_case(&self) -> Option<StageSpecialCase> {
None
}
}
pub trait RenderPipelineInOutStage: Any + std::fmt::Display + Send + Sync {
type InputT: ImageDataType;
type OutputT: ImageDataType;
const BORDER: (u8, u8);
const SHIFT: (u8, u8);
fn process_row_chunk(
&self,
position: (usize, usize),
xsize: usize,
input_rows: &Channels<Self::InputT>,
output_rows: &mut ChannelsMut<Self::OutputT>,
state: Option<&mut (dyn Any + Send)>,
);
fn init_local_state(&self, _thread_index: usize) -> Result<Option<Box<dyn Any + Send>>> {
Ok(None)
}
fn uses_channel(&self, c: usize) -> bool;
fn is_special_case(&self) -> Option<StageSpecialCase> {
None
}
}
pub(crate) trait RenderPipeline: Sized {
type Buffer: 'static;
fn new_from_shared(shared: RenderPipelineShared<Self::Buffer>) -> Result<Self>;
fn get_buffer<T: ImageDataType>(&mut self, channel: usize) -> Result<Image<T>>;
fn set_buffer_for_group<T: ImageDataType>(
&mut self,
channel: usize,
group_id: usize,
complete: bool,
buf: Image<T>,
buffer_splitter: &mut BufferSplitter,
) -> Result<()>;
fn check_buffer_sizes(&self, buffers: &mut [Option<JxlOutputBuffer>]) -> Result<()>;
fn render_outside_frame(&mut self, buffer_splitter: &mut BufferSplitter) -> Result<()>;
fn mark_group_to_rerender(&mut self, g: usize);
fn box_inout_stage<S: RenderPipelineInOutStage + Send + Sync>(
stage: S,
) -> Box<dyn RunInOutStage<Self::Buffer> + Send + Sync>;
fn box_inplace_stage<S: RenderPipelineInPlaceStage + Send + Sync>(
stage: S,
) -> Box<dyn RunInPlaceStage<Self::Buffer> + Send + Sync>;
fn used_channel_mask(&self) -> &[bool];
fn needs_border_rendering(&self) -> bool;
fn prepare_final_rerender(&mut self);
fn render_all_groups_full_readiness(
&mut self,
buffer_splitter: &mut BufferSplitter,
) -> Result<()>;
fn finish_final_rerender(&mut self);
}