use j2k_core::{BackendKind, BackendRequest, Downscale, PixelFormat, Rect};
use crate::{batch, routing, Surface, SurfaceResidency};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[doc(hidden)]
pub enum DecodeOperation {
Full,
Region,
Scaled,
RegionScaled,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MetalDecodeOp {
Full,
Region(Rect),
Scaled(Downscale),
RegionScaled {
roi: Rect,
scale: Downscale,
},
}
impl MetalDecodeOp {
pub(crate) const fn report_operation(self) -> DecodeOperation {
match self {
Self::Full => DecodeOperation::Full,
Self::Region(_) => DecodeOperation::Region,
Self::Scaled(_) => DecodeOperation::Scaled,
Self::RegionScaled { .. } => DecodeOperation::RegionScaled,
}
}
pub(crate) const fn batch_op(self) -> batch::BatchOp {
match self {
Self::Full => batch::BatchOp::Full,
Self::Region(roi) => batch::BatchOp::Region(roi),
Self::Scaled(scale) => batch::BatchOp::Scaled(scale),
Self::RegionScaled { roi, scale } => batch::BatchOp::RegionScaled { roi, scale },
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MetalDecodeRequest {
pub fmt: PixelFormat,
pub op: MetalDecodeOp,
pub backend: BackendRequest,
}
impl MetalDecodeRequest {
pub const fn full(fmt: PixelFormat, backend: BackendRequest) -> Self {
Self {
fmt,
op: MetalDecodeOp::Full,
backend,
}
}
pub const fn region(fmt: PixelFormat, roi: Rect, backend: BackendRequest) -> Self {
Self {
fmt,
op: MetalDecodeOp::Region(roi),
backend,
}
}
pub const fn scaled(fmt: PixelFormat, scale: Downscale, backend: BackendRequest) -> Self {
Self {
fmt,
op: MetalDecodeOp::Scaled(scale),
backend,
}
}
pub const fn region_scaled(
fmt: PixelFormat,
roi: Rect,
scale: Downscale,
backend: BackendRequest,
) -> Self {
Self {
fmt,
op: MetalDecodeOp::RegionScaled { roi, scale },
backend,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[doc(hidden)]
pub struct DecodeRouteReport {
pub operation: DecodeOperation,
pub requested_backend: BackendRequest,
pub selected_backend: BackendKind,
pub pixel_format: PixelFormat,
pub surface_residency: SurfaceResidency,
pub fallback_reason: Option<&'static str>,
}
impl DecodeRouteReport {
fn from_surface(
operation: DecodeOperation,
requested_backend: BackendRequest,
pixel_format: PixelFormat,
surface: &Surface,
) -> Self {
Self {
operation,
requested_backend,
selected_backend: surface.backend,
pixel_format,
surface_residency: surface.residency,
fallback_reason: decode_fallback_reason(requested_backend, surface.backend),
}
}
}
#[derive(Clone)]
#[doc(hidden)]
pub struct DecodeSurfaceWithReport {
pub surface: Surface,
pub report: DecodeRouteReport,
}
fn decode_fallback_reason(
requested_backend: BackendRequest,
selected_backend: BackendKind,
) -> Option<&'static str> {
if requested_backend == BackendRequest::Auto && selected_backend == BackendKind::Cpu {
Some(routing::AUTO_DECODE_CPU_FALLBACK_REASON)
} else {
None
}
}
pub(super) fn surface_with_report(
surface: Surface,
operation: DecodeOperation,
requested_backend: BackendRequest,
pixel_format: PixelFormat,
) -> DecodeSurfaceWithReport {
let report =
DecodeRouteReport::from_surface(operation, requested_backend, pixel_format, &surface);
DecodeSurfaceWithReport { surface, report }
}