Skip to content

Commit a3639a1

Browse files
Implement SDL_UpdateNVTexture
1 parent 57b3169 commit a3639a1

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

src/sdl2/render.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,6 +2181,115 @@ impl InternalTexture {
21812181
}
21822182
}
21832183

2184+
#[doc(alias = "SDL_UpdateNVTexture")]
2185+
pub fn update_nv<R>(
2186+
&mut self,
2187+
rect: R,
2188+
y_plane: &[u8],
2189+
y_pitch: usize,
2190+
uv_plane: &[u8],
2191+
uv_pitch: usize,
2192+
) -> Result<(), UpdateTextureYUVError>
2193+
where
2194+
R: Into<Option<Rect>>,
2195+
{
2196+
use self::UpdateTextureYUVError::*;
2197+
2198+
let rect = rect.into();
2199+
2200+
let rect_raw_ptr = match rect {
2201+
Some(ref rect) => rect.raw(),
2202+
None => ptr::null(),
2203+
};
2204+
2205+
if let Some(ref r) = rect {
2206+
if r.x() % 2 != 0 {
2207+
return Err(XMustBeMultipleOfTwoForFormat(r.x()));
2208+
} else if r.y() % 2 != 0 {
2209+
return Err(YMustBeMultipleOfTwoForFormat(r.y()));
2210+
} else if r.width() % 2 != 0 {
2211+
return Err(WidthMustBeMultipleOfTwoForFormat(r.width()));
2212+
} else if r.height() % 2 != 0 {
2213+
return Err(HeightMustBeMultipleOfTwoForFormat(r.height()));
2214+
}
2215+
};
2216+
2217+
// If the destination rectangle lies outside the texture boundaries,
2218+
// SDL_UpdateNVTexture will write outside allocated texture memory.
2219+
let tex_info = self.query();
2220+
if let Some(ref r) = rect {
2221+
let tex_rect = Rect::new(0, 0, tex_info.width, tex_info.height);
2222+
let inside = match r.intersection(tex_rect) {
2223+
Some(intersection) => intersection == *r,
2224+
None => false,
2225+
};
2226+
// The destination rectangle cannot lie outside the texture boundaries
2227+
if !inside {
2228+
return Err(RectNotInsideTexture(*r));
2229+
}
2230+
}
2231+
2232+
// We need the height in order to check the array slice lengths.
2233+
// Checking the lengths can prevent buffer overruns in SDL_UpdateNVTexture.
2234+
let height = match rect {
2235+
Some(ref r) => r.height(),
2236+
None => tex_info.height,
2237+
} as usize;
2238+
2239+
//let wrong_length =
2240+
if y_plane.len() != (y_pitch * height) {
2241+
return Err(InvalidPlaneLength {
2242+
plane: "y",
2243+
length: y_plane.len(),
2244+
pitch: y_pitch,
2245+
height,
2246+
});
2247+
}
2248+
if uv_plane.len() != (uv_pitch * height) {
2249+
return Err(InvalidPlaneLength {
2250+
plane: "uv",
2251+
length: uv_plane.len(),
2252+
pitch: uv_pitch,
2253+
height: height,
2254+
});
2255+
}
2256+
2257+
let y_pitch = match validate_int(y_pitch as u32, "y_pitch") {
2258+
Ok(p) => p,
2259+
Err(_) => {
2260+
return Err(PitchOverflows {
2261+
plane: "y",
2262+
value: y_pitch,
2263+
})
2264+
}
2265+
};
2266+
let uv_pitch = match validate_int(uv_pitch as u32, "uv_pitch") {
2267+
Ok(p) => p,
2268+
Err(_) => {
2269+
return Err(PitchOverflows {
2270+
plane: "uv",
2271+
value: uv_pitch,
2272+
})
2273+
}
2274+
};
2275+
2276+
let result = unsafe {
2277+
sys::SDL_UpdateNVTexture(
2278+
self.raw,
2279+
rect_raw_ptr,
2280+
y_plane.as_ptr(),
2281+
y_pitch,
2282+
uv_plane.as_ptr(),
2283+
uv_pitch,
2284+
)
2285+
};
2286+
if result != 0 {
2287+
Err(SdlError(get_error()))
2288+
} else {
2289+
Ok(())
2290+
}
2291+
}
2292+
21842293
#[doc(alias = "SDL_LockTexture")]
21852294
pub fn with_lock<F, R, R2>(&mut self, rect: R2, func: F) -> Result<R, String>
21862295
where
@@ -2346,6 +2455,22 @@ impl<'r> Texture<'r> {
23462455
.update_yuv(rect, y_plane, y_pitch, u_plane, u_pitch, v_plane, v_pitch)
23472456
}
23482457

2458+
/// Update a rectangle within a planar NV12 or NV21 texture with new pixel data.
2459+
#[inline]
2460+
pub fn update_nv<R>(
2461+
&mut self,
2462+
rect: R,
2463+
y_plane: &[u8],
2464+
y_pitch: usize,
2465+
uv_plane: &[u8],
2466+
uv_pitch: usize,
2467+
) -> Result<(), UpdateTextureYUVError>
2468+
where
2469+
R: Into<Option<Rect>>,
2470+
{
2471+
InternalTexture { raw: self.raw }.update_nv(rect, y_plane, y_pitch, uv_plane, uv_pitch)
2472+
}
2473+
23492474
/// Locks the texture for **write-only** pixel access.
23502475
/// The texture must have been created with streaming access.
23512476
///
@@ -2543,6 +2668,22 @@ impl Texture {
25432668
.update_yuv(rect, y_plane, y_pitch, u_plane, u_pitch, v_plane, v_pitch)
25442669
}
25452670

2671+
/// Update a rectangle within a planar NV12 or NV21 texture with new pixel data.
2672+
#[inline]
2673+
pub fn update_nv<R>(
2674+
&mut self,
2675+
rect: R,
2676+
y_plane: &[u8],
2677+
y_pitch: usize,
2678+
uv_plane: &[u8],
2679+
uv_pitch: usize,
2680+
) -> Result<(), UpdateTextureYUVError>
2681+
where
2682+
R: Into<Option<Rect>>,
2683+
{
2684+
InternalTexture { raw: self.raw }.update_nv(rect, y_plane, y_pitch, uv_plane, uv_pitch)
2685+
}
2686+
25462687
/// Locks the texture for **write-only** pixel access.
25472688
/// The texture must have been created with streaming access.
25482689
///

0 commit comments

Comments
 (0)