implements PLN-0110

This commit is contained in:
bQUARKz 2026-06-15 16:01:47 +01:00
parent 3916a652b2
commit 12d314a62d
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
4 changed files with 131 additions and 2 deletions

View File

@ -17,6 +17,7 @@ pub mod input_signals;
pub mod log;
pub mod native_helpers;
pub mod native_interface;
pub mod owned_frame;
pub mod pad_bridge;
pub mod platform;
pub mod primitives;
@ -44,6 +45,7 @@ pub use host_return::HostReturn;
pub use input_signals::InputSignals;
pub use native_helpers::{expect_bool, expect_int};
pub use native_interface::{NativeInterface, SyscallId};
pub use owned_frame::{OwnedRgba8888Frame, OwnedRgba8888FrameError};
pub use pad_bridge::PadBridge;
pub use platform::{
AssetStoragePlatform, AudioPlatform, ClockPacingPlatform, Game2DFrameComposer, InputPlatform,

View File

@ -0,0 +1,127 @@
use crate::render_submission::{FrameId, RenderOwnership};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OwnedRgba8888Frame {
pub frame_id: FrameId,
pub ownership: RenderOwnership,
pub width: usize,
pub height: usize,
pub stride_pixels: usize,
pub pixels: Vec<u32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OwnedRgba8888FrameError {
EmptyDimensions,
StrideTooSmall,
PixelBufferTooSmall,
}
impl OwnedRgba8888Frame {
pub fn new(
frame_id: FrameId,
ownership: RenderOwnership,
width: usize,
height: usize,
stride_pixels: usize,
pixels: Vec<u32>,
) -> Result<Self, OwnedRgba8888FrameError> {
if width == 0 || height == 0 {
return Err(OwnedRgba8888FrameError::EmptyDimensions);
}
if stride_pixels < width {
return Err(OwnedRgba8888FrameError::StrideTooSmall);
}
let required_len = stride_pixels
.checked_mul(height)
.ok_or(OwnedRgba8888FrameError::PixelBufferTooSmall)?;
if pixels.len() < required_len {
return Err(OwnedRgba8888FrameError::PixelBufferTooSmall);
}
Ok(Self { frame_id, ownership, width, height, stride_pixels, pixels })
}
pub fn packed(
frame_id: FrameId,
ownership: RenderOwnership,
width: usize,
height: usize,
pixels: Vec<u32>,
) -> Result<Self, OwnedRgba8888FrameError> {
Self::new(frame_id, ownership, width, height, width, pixels)
}
pub fn required_pixel_len(&self) -> usize {
self.stride_pixels * self.height
}
pub fn row(&self, y: usize) -> Option<&[u32]> {
if y >= self.height {
return None;
}
let start = y * self.stride_pixels;
Some(&self.pixels[start..start + self.width])
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::app_mode::AppMode;
fn ownership() -> RenderOwnership {
RenderOwnership::new(11, AppMode::Game, 42)
}
#[test]
fn owned_rgba8888_frame_preserves_metadata_and_pixels() {
let pixels = vec![0x11223344, 0x55667788, 0x99AABBCC, 0xDDEEFF00];
let frame = OwnedRgba8888Frame::packed(FrameId::new(7), ownership(), 2, 2, pixels.clone())
.expect("valid packed RGBA8888 frame");
assert_eq!(frame.frame_id, FrameId::new(7));
assert_eq!(frame.ownership, ownership());
assert_eq!(frame.width, 2);
assert_eq!(frame.height, 2);
assert_eq!(frame.stride_pixels, 2);
assert_eq!(frame.pixels, pixels);
assert_eq!(frame.required_pixel_len(), 4);
}
#[test]
fn checked_constructor_rejects_empty_dimensions() {
let err = OwnedRgba8888Frame::new(FrameId::ZERO, ownership(), 0, 1, 1, vec![0])
.expect_err("zero width should be rejected");
assert_eq!(err, OwnedRgba8888FrameError::EmptyDimensions);
}
#[test]
fn checked_constructor_rejects_stride_smaller_than_width() {
let err = OwnedRgba8888Frame::new(FrameId::ZERO, ownership(), 3, 1, 2, vec![0, 0, 0])
.expect_err("stride smaller than width should be rejected");
assert_eq!(err, OwnedRgba8888FrameError::StrideTooSmall);
}
#[test]
fn checked_constructor_rejects_short_pixel_buffer() {
let err = OwnedRgba8888Frame::new(FrameId::ZERO, ownership(), 2, 2, 3, vec![0; 5])
.expect_err("buffer shorter than stride * height should be rejected");
assert_eq!(err, OwnedRgba8888FrameError::PixelBufferTooSmall);
}
#[test]
fn row_returns_visible_width_without_stride_padding() {
let frame =
OwnedRgba8888Frame::new(FrameId::ZERO, ownership(), 2, 2, 3, vec![1, 2, 99, 3, 4, 88])
.expect("valid padded frame");
assert_eq!(frame.row(0), Some(&[1, 2][..]));
assert_eq!(frame.row(1), Some(&[3, 4][..]));
assert_eq!(frame.row(2), None);
}
}

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
id: PLN-0110
ticket: real-render-worker-establishment
title: Define Owned RGBA8888 Frame Contract
status: open
status: done
created: 2026-06-15
completed:
ref_decisions: [DEC-0033]