1use std::{
2 iter::FusedIterator,
3 marker::PhantomData,
4 ops::{Index, IndexMut},
5 slice,
6};
7
8use v_frame::{
9 pixel::Pixel,
10 plane::{Plane, PlaneConfig, PlaneOffset},
11};
12
13use super::block::{BlockOffset, BLOCK_TO_PLANE_SHIFT};
14
15#[derive(Debug)]
20pub struct PlaneRegion<'a, T: Pixel> {
21 data: *const T, pub plane_cfg: &'a PlaneConfig,
23 rect: Rect,
25 phantom: PhantomData<&'a T>,
26}
27
28#[derive(Debug)]
33pub struct PlaneRegionMut<'a, T: Pixel> {
34 data: *mut T, pub plane_cfg: &'a PlaneConfig,
36 rect: Rect,
37 phantom: PhantomData<&'a mut T>,
38}
39
40macro_rules! plane_region_common {
42 ($name:ident, $as_ptr:ident $(,$opt_mut:tt)?) => {
46 impl<'a, T: Pixel> $name<'a, T> {
47 #[cold]
48 pub fn empty(plane_cfg : &'a PlaneConfig) -> Self {
49 return Self {
50 data: std::ptr::null_mut::<T>(),
54 plane_cfg,
55 rect: Rect::default(),
56 phantom: PhantomData,
57 }
58 }
59
60 pub fn from_slice(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self {
64 if cfg.width == 0 || cfg.height == 0 {
65 return Self::empty(&cfg);
66 }
67 assert!(rect.x >= -(cfg.xorigin as isize));
68 assert!(rect.y >= -(cfg.yorigin as isize));
69 assert!(cfg.xorigin as isize + rect.x + rect.width as isize <= cfg.stride as isize);
70 assert!(cfg.yorigin as isize + rect.y + rect.height as isize <= cfg.alloc_height as isize);
71
72 unsafe { Self::from_slice_unsafe(data, cfg, rect)}
74 }
75
76 unsafe fn from_slice_unsafe(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self {
77 let origin = (cfg.yorigin as isize + rect.y) * cfg.stride as isize + cfg.xorigin as isize + rect.x;
78 Self {
79 data: data.$as_ptr().offset(origin),
80 plane_cfg: cfg,
81 rect,
82 phantom: PhantomData,
83 }
84 }
85
86 pub fn new(plane: &'a $($opt_mut)? Plane<T>, rect: Rect) -> Self {
87 Self::from_slice(& $($opt_mut)? plane.data, &plane.cfg, rect)
88 }
89
90 #[allow(dead_code)]
91 pub fn new_from_plane(plane: &'a $($opt_mut)? Plane<T>) -> Self {
92 let rect = Rect {
93 x: 0,
94 y: 0,
95 width: plane.cfg.stride - plane.cfg.xorigin,
96 height: plane.cfg.alloc_height - plane.cfg.yorigin,
97 };
98
99 unsafe { Self::from_slice_unsafe(& $($opt_mut)? plane.data, &plane.cfg, rect) }
101 }
102
103 #[allow(dead_code)]
104 pub fn data_ptr(&self) -> *const T {
105 self.data
106 }
107
108 pub fn rect(&self) -> &Rect {
109 &self.rect
110 }
111
112 #[allow(dead_code)]
113 pub fn rows_iter(&self) -> PlaneRegionRowsIter<'_, T> {
114 PlaneRegionRowsIter {
115 data: self.data,
116 stride: self.plane_cfg.stride,
117 width: self.rect.width,
118 remaining: self.rect.height,
119 phantom: PhantomData,
120 }
121 }
122
123 #[allow(dead_code)]
124 pub fn vert_windows(&self, h: usize) -> VertWindows<'_, T> {
125 VertWindows {
126 data: self.data,
127 plane_cfg: self.plane_cfg,
128 remaining: (self.rect.height as isize - h as isize + 1).max(0) as usize,
129 output_rect: Rect {
130 x: self.rect.x,
131 y: self.rect.y,
132 width: self.rect.width,
133 height: h
134 }
135 }
136 }
137
138 #[allow(dead_code)]
139 pub fn horz_windows(&self, w: usize) -> HorzWindows<'_, T> {
140 HorzWindows {
141 data: self.data,
142 plane_cfg: self.plane_cfg,
143 remaining: (self.rect.width as isize - w as isize + 1).max(0) as usize,
144 output_rect: Rect {
145 x: self.rect.x,
146 y: self.rect.y,
147 width: w,
148 height: self.rect.height
149 }
150 }
151 }
152
153 #[allow(dead_code)]
183 pub fn subregion(&self, area: Area) -> PlaneRegion<'_, T> {
184 if self.data.is_null() {
185 return PlaneRegion::empty(&self.plane_cfg);
186 }
187 let rect = area.to_rect(
188 self.plane_cfg.xdec,
189 self.plane_cfg.ydec,
190 self.rect.width,
191 self.rect.height,
192 );
193 assert!(rect.x >= 0 && rect.x as usize <= self.rect.width);
194 assert!(rect.y >= 0 && rect.y as usize <= self.rect.height);
195 let data = unsafe {
197 self.data.add(rect.y as usize * self.plane_cfg.stride + rect.x as usize)
198 };
199 let absolute_rect = Rect {
200 x: self.rect.x + rect.x,
201 y: self.rect.y + rect.y,
202 width: rect.width,
203 height: rect.height,
204 };
205 PlaneRegion {
206 data,
207 plane_cfg: &self.plane_cfg,
208 rect: absolute_rect,
209 phantom: PhantomData,
210 }
211 }
212 }
213
214 unsafe impl<T: Pixel> Send for $name<'_, T> {}
215 unsafe impl<T: Pixel> Sync for $name<'_, T> {}
216
217 impl<T: Pixel> Index<usize> for $name<'_, T> {
218 type Output = [T];
219
220 fn index(&self, index: usize) -> &Self::Output {
221 assert!(index < self.rect.height);
222 unsafe {
224 let ptr = self.data.add(index * self.plane_cfg.stride);
225 slice::from_raw_parts(ptr, self.rect.width)
226 }
227 }
228 }
229 }
230}
231
232plane_region_common!(PlaneRegion, as_ptr);
233plane_region_common!(PlaneRegionMut, as_mut_ptr, mut);
234
235impl<T: Pixel> PlaneRegionMut<'_, T> {
236 pub fn data_ptr_mut(&mut self) -> *mut T {
237 self.data
238 }
239
240 pub fn rows_iter_mut(&mut self) -> PlaneRegionRowsIterMut<'_, T> {
241 PlaneRegionRowsIterMut {
242 data: self.data,
243 stride: self.plane_cfg.stride,
244 width: self.rect.width,
245 remaining: self.rect.height,
246 phantom: PhantomData,
247 }
248 }
249
250 pub fn as_const(&self) -> PlaneRegion<'_, T> {
251 PlaneRegion {
252 data: self.data,
253 plane_cfg: self.plane_cfg,
254 rect: self.rect,
255 phantom: PhantomData,
256 }
257 }
258}
259
260impl<T: Pixel> IndexMut<usize> for PlaneRegionMut<'_, T> {
261 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
262 assert!(index < self.rect.height);
263 unsafe {
265 let ptr = self.data.add(index * self.plane_cfg.stride);
266 slice::from_raw_parts_mut(ptr, self.rect.width)
267 }
268 }
269}
270
271pub struct PlaneRegionRowsIter<'a, T: Pixel> {
273 data: *const T,
274 stride: usize,
275 width: usize,
276 remaining: usize,
277 phantom: PhantomData<&'a T>,
278}
279
280impl<'a, T: Pixel> Iterator for PlaneRegionRowsIter<'a, T> {
281 type Item = &'a [T];
282
283 fn next(&mut self) -> Option<Self::Item> {
284 if self.remaining > 0 {
285 let row = unsafe {
288 let ptr = self.data;
289 self.data = self.data.add(self.stride);
290 slice::from_raw_parts(ptr, self.width)
291 };
292 self.remaining -= 1;
293 Some(row)
294 } else {
295 None
296 }
297 }
298
299 fn size_hint(&self) -> (usize, Option<usize>) {
300 (self.remaining, Some(self.remaining))
301 }
302}
303
304pub struct PlaneRegionRowsIterMut<'a, T: Pixel> {
306 data: *mut T,
307 stride: usize,
308 width: usize,
309 remaining: usize,
310 phantom: PhantomData<&'a mut T>,
311}
312
313impl<'a, T: Pixel> Iterator for PlaneRegionRowsIterMut<'a, T> {
314 type Item = &'a mut [T];
315
316 fn next(&mut self) -> Option<Self::Item> {
317 if self.remaining > 0 {
318 let row = unsafe {
321 let ptr = self.data;
322 self.data = self.data.add(self.stride);
323 slice::from_raw_parts_mut(ptr, self.width)
324 };
325 self.remaining -= 1;
326 Some(row)
327 } else {
328 None
329 }
330 }
331
332 fn size_hint(&self) -> (usize, Option<usize>) {
333 (self.remaining, Some(self.remaining))
334 }
335}
336
337impl<T: Pixel> ExactSizeIterator for PlaneRegionRowsIter<'_, T> {
338}
339impl<T: Pixel> FusedIterator for PlaneRegionRowsIter<'_, T> {
340}
341impl<T: Pixel> ExactSizeIterator for PlaneRegionRowsIterMut<'_, T> {
342}
343impl<T: Pixel> FusedIterator for PlaneRegionRowsIterMut<'_, T> {
344}
345
346pub struct VertWindows<'a, T: Pixel> {
347 data: *const T,
348 plane_cfg: &'a PlaneConfig,
349 remaining: usize,
350 output_rect: Rect,
351}
352
353pub struct HorzWindows<'a, T: Pixel> {
354 data: *const T,
355 plane_cfg: &'a PlaneConfig,
356 remaining: usize,
357 output_rect: Rect,
358}
359
360impl<'a, T: Pixel> Iterator for VertWindows<'a, T> {
361 type Item = PlaneRegion<'a, T>;
362
363 fn next(&mut self) -> Option<Self::Item> {
364 self.nth(0)
365 }
366
367 fn size_hint(&self) -> (usize, Option<usize>) {
368 (self.remaining, Some(self.remaining))
369 }
370
371 fn nth(&mut self, n: usize) -> Option<Self::Item> {
372 if self.remaining > n {
373 self.data = unsafe { self.data.add(self.plane_cfg.stride * n) };
375 self.output_rect.y += n as isize;
376 let output = PlaneRegion {
377 data: self.data,
378 plane_cfg: self.plane_cfg,
379 rect: self.output_rect,
380 phantom: PhantomData,
381 };
382 self.data = unsafe { self.data.add(self.plane_cfg.stride) };
384 self.output_rect.y += 1;
385 self.remaining -= n + 1;
386 Some(output)
387 } else {
388 None
389 }
390 }
391}
392
393impl<'a, T: Pixel> Iterator for HorzWindows<'a, T> {
394 type Item = PlaneRegion<'a, T>;
395
396 fn next(&mut self) -> Option<Self::Item> {
397 self.nth(0)
398 }
399
400 fn size_hint(&self) -> (usize, Option<usize>) {
401 (self.remaining, Some(self.remaining))
402 }
403
404 fn nth(&mut self, n: usize) -> Option<Self::Item> {
405 if self.remaining > n {
406 self.data = unsafe { self.data.add(n) };
408 self.output_rect.x += n as isize;
409 let output = PlaneRegion {
410 data: self.data,
411 plane_cfg: self.plane_cfg,
412 rect: self.output_rect,
413 phantom: PhantomData,
414 };
415 self.data = unsafe { self.data.add(1) };
417 self.output_rect.x += 1;
418 self.remaining -= n + 1;
419 Some(output)
420 } else {
421 None
422 }
423 }
424}
425
426impl<T: Pixel> ExactSizeIterator for VertWindows<'_, T> {
427}
428impl<T: Pixel> FusedIterator for VertWindows<'_, T> {
429}
430impl<T: Pixel> ExactSizeIterator for HorzWindows<'_, T> {
431}
432impl<T: Pixel> FusedIterator for HorzWindows<'_, T> {
433}
434
435#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
437pub struct Rect {
438 pub x: isize,
440 pub y: isize,
441 pub width: usize,
442 pub height: usize,
443}
444
445#[derive(Debug, Clone, Copy)]
459pub enum Area {
460 Rect(Rect),
462 StartingAt { x: isize, y: isize },
465 BlockStartingAt { bo: BlockOffset },
468}
469
470impl Area {
471 pub const fn to_rect(
477 self,
478 xdec: usize,
479 ydec: usize,
480 parent_width: usize,
481 parent_height: usize,
482 ) -> Rect {
483 match self {
484 Area::Rect(rect) => rect,
485 Area::StartingAt { x, y } => Rect {
486 x,
487 y,
488 width: (parent_width as isize - x) as usize,
489 height: (parent_height as isize - y) as usize,
490 },
491 Area::BlockStartingAt { bo } => {
492 let x = (bo.x >> xdec << BLOCK_TO_PLANE_SHIFT) as isize;
493 let y = (bo.y >> ydec << BLOCK_TO_PLANE_SHIFT) as isize;
494 Rect {
495 x,
496 y,
497 width: (parent_width as isize - x) as usize,
498 height: (parent_height as isize - y) as usize,
499 }
500 }
501 }
502 }
503}
504
505pub trait AsRegion<T: Pixel> {
506 fn as_region(&self) -> PlaneRegion<'_, T>;
507 fn region(&self, area: Area) -> PlaneRegion<'_, T>;
508 fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T>;
509}
510
511impl<T: Pixel> AsRegion<T> for Plane<T> {
512 fn as_region(&self) -> PlaneRegion<'_, T> {
513 PlaneRegion::new_from_plane(self)
514 }
515
516 fn region(&self, area: Area) -> PlaneRegion<'_, T> {
517 let rect = area.to_rect(
518 self.cfg.xdec,
519 self.cfg.ydec,
520 self.cfg.stride - self.cfg.xorigin,
521 self.cfg.alloc_height - self.cfg.yorigin,
522 );
523 PlaneRegion::new(self, rect)
524 }
525
526 fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T> {
527 let rect = area.to_rect(
528 self.cfg.xdec,
529 self.cfg.ydec,
530 self.cfg.stride - self.cfg.xorigin,
531 self.cfg.alloc_height - self.cfg.yorigin,
532 );
533 PlaneRegionMut::new(self, rect)
534 }
535}
536
537#[derive(Clone, Copy, Debug, PartialEq, Eq)]
540pub struct PlaneBlockOffset(pub BlockOffset);
541
542impl PlaneBlockOffset {
543 pub const fn to_luma_plane_offset(self) -> PlaneOffset {
545 self.0.to_luma_plane_offset()
546 }
547}