1use j2k_core::{BackendKind, BackendRequest, Downscale, PixelFormat, Rect};
4
5use crate::{batch, routing, Surface, SurfaceResidency};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[doc(hidden)]
10pub enum DecodeOperation {
11 Full,
13 Region,
15 Scaled,
17 RegionScaled,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum MetalDecodeOp {
24 Full,
26 Region(Rect),
28 Scaled(Downscale),
30 RegionScaled {
32 roi: Rect,
34 scale: Downscale,
36 },
37}
38
39impl MetalDecodeOp {
40 pub(crate) const fn report_operation(self) -> DecodeOperation {
41 match self {
42 Self::Full => DecodeOperation::Full,
43 Self::Region(_) => DecodeOperation::Region,
44 Self::Scaled(_) => DecodeOperation::Scaled,
45 Self::RegionScaled { .. } => DecodeOperation::RegionScaled,
46 }
47 }
48
49 pub(crate) const fn batch_op(self) -> batch::BatchOp {
50 match self {
51 Self::Full => batch::BatchOp::Full,
52 Self::Region(roi) => batch::BatchOp::Region(roi),
53 Self::Scaled(scale) => batch::BatchOp::Scaled(scale),
54 Self::RegionScaled { roi, scale } => batch::BatchOp::RegionScaled { roi, scale },
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct MetalDecodeRequest {
62 pub fmt: PixelFormat,
64 pub op: MetalDecodeOp,
66 pub backend: BackendRequest,
68}
69
70impl MetalDecodeRequest {
71 pub const fn full(fmt: PixelFormat, backend: BackendRequest) -> Self {
73 Self {
74 fmt,
75 op: MetalDecodeOp::Full,
76 backend,
77 }
78 }
79
80 pub const fn region(fmt: PixelFormat, roi: Rect, backend: BackendRequest) -> Self {
82 Self {
83 fmt,
84 op: MetalDecodeOp::Region(roi),
85 backend,
86 }
87 }
88
89 pub const fn scaled(fmt: PixelFormat, scale: Downscale, backend: BackendRequest) -> Self {
91 Self {
92 fmt,
93 op: MetalDecodeOp::Scaled(scale),
94 backend,
95 }
96 }
97
98 pub const fn region_scaled(
100 fmt: PixelFormat,
101 roi: Rect,
102 scale: Downscale,
103 backend: BackendRequest,
104 ) -> Self {
105 Self {
106 fmt,
107 op: MetalDecodeOp::RegionScaled { roi, scale },
108 backend,
109 }
110 }
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115#[doc(hidden)]
116pub struct DecodeRouteReport {
117 pub operation: DecodeOperation,
119 pub requested_backend: BackendRequest,
121 pub selected_backend: BackendKind,
123 pub pixel_format: PixelFormat,
125 pub surface_residency: SurfaceResidency,
127 pub fallback_reason: Option<&'static str>,
129}
130
131impl DecodeRouteReport {
132 fn from_surface(
133 operation: DecodeOperation,
134 requested_backend: BackendRequest,
135 pixel_format: PixelFormat,
136 surface: &Surface,
137 ) -> Self {
138 Self {
139 operation,
140 requested_backend,
141 selected_backend: surface.backend,
142 pixel_format,
143 surface_residency: surface.residency,
144 fallback_reason: decode_fallback_reason(requested_backend, surface.backend),
145 }
146 }
147}
148
149#[derive(Clone)]
151#[doc(hidden)]
152pub struct DecodeSurfaceWithReport {
153 pub surface: Surface,
155 pub report: DecodeRouteReport,
157}
158
159fn decode_fallback_reason(
160 requested_backend: BackendRequest,
161 selected_backend: BackendKind,
162) -> Option<&'static str> {
163 if requested_backend == BackendRequest::Auto && selected_backend == BackendKind::Cpu {
164 Some(routing::AUTO_DECODE_CPU_FALLBACK_REASON)
165 } else {
166 None
167 }
168}
169
170pub(super) fn surface_with_report(
171 surface: Surface,
172 operation: DecodeOperation,
173 requested_backend: BackendRequest,
174 pixel_format: PixelFormat,
175) -> DecodeSurfaceWithReport {
176 let report =
177 DecodeRouteReport::from_surface(operation, requested_backend, pixel_format, &surface);
178 DecodeSurfaceWithReport { surface, report }
179}