Browse Source

Update ctru-rs APIs based on split screen PR

pull/4/head
Ian Chamberlain 2 years ago
parent
commit
894eb66806
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 2
      citro3d-sys/build.rs
  2. 2
      citro3d/Cargo.toml
  3. 14
      citro3d/examples/triangle.rs
  4. 6
      citro3d/src/lib.rs
  5. 51
      citro3d/src/render.rs

2
citro3d-sys/build.rs

@ -6,7 +6,7 @@ fn main() {
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=DEVKITPRO"); println!("cargo:rerun-if-env-changed=DEVKITPRO");
println!("cargo:rustc-link-search=native={}/libctru/lib", dkp_path); println!("cargo:rustc-link-search=native={dkp_path}/libctru/lib");
println!( println!(
"cargo:rustc-link-lib=static={}", "cargo:rustc-link-lib=static={}",
match debug_symbols.as_str() { match debug_symbols.as_str() {

2
citro3d/Cargo.toml

@ -7,7 +7,7 @@ edition = "2021"
bitflags = "1.3.2" bitflags = "1.3.2"
bytemuck = { version = "1.10.0", features = ["extern_crate_std"] } bytemuck = { version = "1.10.0", features = ["extern_crate_std"] }
citro3d-sys = { git = "https://github.com/ian-h-chamberlain/citro3d-rs.git" } citro3d-sys = { git = "https://github.com/ian-h-chamberlain/citro3d-rs.git" }
ctru-rs = { git = "https://github.com/Meziu/ctru-rs.git" } ctru-rs = { git = "https://github.com/rust3ds/ctru-rs.git" }
libc = "0.2.125" libc = "0.2.125"
[dev-dependencies] [dev-dependencies]

14
citro3d/examples/triangle.rs

@ -1,16 +1,16 @@
use citro3d::render::ClearFlags;
use citro3d::{include_aligned_bytes, shader}; use citro3d::{include_aligned_bytes, shader};
use citro3d_sys::C3D_Mtx; use citro3d_sys::C3D_Mtx;
use ctru::gfx::{Gfx, Side}; use ctru::gfx::{Gfx, Screen};
use ctru::services::apt::Apt; use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad}; use ctru::services::hid::{Hid, KeyPad};
use ctru::services::soc::Soc; use ctru::services::soc::Soc;
use citro3d::render::ClearFlags;
use std::ffi::CStr; use std::ffi::CStr;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)]
struct Vec3 { struct Vec3 {
x: f32, x: f32,
y: f32, y: f32,
@ -24,6 +24,7 @@ impl Vec3 {
} }
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)]
struct Vertex { struct Vertex {
pos: Vec3, pos: Vec3,
color: Vec3, color: Vec3,
@ -58,7 +59,7 @@ fn main() {
let apt = Apt::init().expect("Couldn't obtain APT controller"); let apt = Apt::init().expect("Couldn't obtain APT controller");
let mut top_screen = gfx.top_screen.borrow_mut(); let mut top_screen = gfx.top_screen.borrow_mut();
let frame_buffer = top_screen.get_raw_framebuffer(Side::Left); let frame_buffer = top_screen.get_raw_framebuffer();
let (width, height) = (frame_buffer.width, frame_buffer.height); let (width, height) = (frame_buffer.width, frame_buffer.height);
let mut instance = citro3d::Instance::new().expect("failed to initialize Citro3D"); let mut instance = citro3d::Instance::new().expect("failed to initialize Citro3D");
@ -66,9 +67,6 @@ fn main() {
let mut render_target = citro3d::render::Target::new(width, height, top_screen, None) let mut render_target = citro3d::render::Target::new(width, height, top_screen, None)
.expect("failed to create render target"); .expect("failed to create render target");
render_target.set_output(Side::Left);
render_target.set_output(Side::Right);
let mut bottom_screen = gfx.bottom_screen.borrow_mut(); let mut bottom_screen = gfx.bottom_screen.borrow_mut();
let frame_buffer = bottom_screen.get_raw_framebuffer(); let frame_buffer = bottom_screen.get_raw_framebuffer();
let (width, height) = (frame_buffer.width, frame_buffer.height); let (width, height) = (frame_buffer.width, frame_buffer.height);
@ -76,8 +74,6 @@ fn main() {
let mut bottom_target = citro3d::render::Target::new(width, height, bottom_screen, None) let mut bottom_target = citro3d::render::Target::new(width, height, bottom_screen, None)
.expect("failed to create bottom screen render target"); .expect("failed to create bottom screen render target");
bottom_target.set_output(Side::Left);
let shader = shader::Library::from_bytes(SHADER_BYTES).unwrap(); let shader = shader::Library::from_bytes(SHADER_BYTES).unwrap();
let vertex_shader = shader.get(0).unwrap(); let vertex_shader = shader.get(0).unwrap();

6
citro3d/src/lib.rs

@ -7,7 +7,6 @@ pub mod texture;
pub mod vbo; pub mod vbo;
use citro3d_sys::C3D_FrameDrawOn; use citro3d_sys::C3D_FrameDrawOn;
use ctru::gfx::Screen;
pub use error::{Error, Result}; pub use error::{Error, Result};
/// The single instance for using `citro3d`. This is the base type that an application /// The single instance for using `citro3d`. This is the base type that an application
@ -44,10 +43,7 @@ impl Instance {
/// # Errors /// # Errors
/// ///
/// Fails if the given target cannot be used for drawing. /// Fails if the given target cannot be used for drawing.
pub fn select_render_target<'s, S: Screen>( pub fn select_render_target(&mut self, target: &render::Target<'_>) -> Result<()> {
&mut self,
target: &render::Target<'s, S>,
) -> Result<()> {
let _ = self; let _ = self;
if unsafe { C3D_FrameDrawOn(target.as_raw()) } { if unsafe { C3D_FrameDrawOn(target.as_raw()) } {
Ok(()) Ok(())

51
citro3d/src/render.rs

@ -7,7 +7,7 @@ use citro3d_sys::{
C3D_RenderTarget, C3D_RenderTargetCreate, C3D_RenderTargetDelete, C3D_DEPTHTYPE, GPU_COLORBUF, C3D_RenderTarget, C3D_RenderTargetCreate, C3D_RenderTargetDelete, C3D_DEPTHTYPE, GPU_COLORBUF,
GPU_DEPTHBUF, GPU_DEPTHBUF,
}; };
use ctru::gfx::{self, Screen}; use ctru::gfx::Screen;
use ctru::services::gspgpu::FramebufferFormat; use ctru::services::gspgpu::FramebufferFormat;
use crate::{Error, Result}; use crate::{Error, Result};
@ -16,13 +16,14 @@ mod transfer;
/// A render target for `citro3d`. Frame data will be written to this target /// A render target for `citro3d`. Frame data will be written to this target
/// to be rendered on the GPU and displayed on the screen. /// to be rendered on the GPU and displayed on the screen.
pub struct Target<'s, S> { pub struct Target<'screen> {
raw: *mut citro3d_sys::C3D_RenderTarget, raw: *mut citro3d_sys::C3D_RenderTarget,
color_format: ColorFormat, // This is unused after construction, but ensures unique access to the
screen: RefMut<'s, S>, // screen this target writes to during rendering
_screen: RefMut<'screen, dyn Screen>,
} }
impl<'s, S> Drop for Target<'s, S> { impl Drop for Target<'_> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
C3D_RenderTargetDelete(self.raw); C3D_RenderTargetDelete(self.raw);
@ -30,10 +31,7 @@ impl<'s, S> Drop for Target<'s, S> {
} }
} }
impl<'s, S> Target<'s, S> impl<'screen> Target<'screen> {
where
S: Screen,
{
/// Create a new render target with the specified size, color format, /// Create a new render target with the specified size, color format,
/// and depth format. /// and depth format.
/// ///
@ -43,10 +41,11 @@ where
pub fn new( pub fn new(
width: u16, width: u16,
height: u16, height: u16,
screen: RefMut<'s, S>, // TODO: is there a use case for a render target that isn't associated with a Screen?
screen: RefMut<'screen, dyn Screen>,
depth_format: Option<DepthFormat>, depth_format: Option<DepthFormat>,
) -> Result<Self> { ) -> Result<Self> {
let color_format = screen.get_framebuffer_format().into(); let color_format: ColorFormat = screen.get_framebuffer_format().into();
let raw = unsafe { let raw = unsafe {
C3D_RenderTargetCreate( C3D_RenderTargetCreate(
@ -58,33 +57,27 @@ where
}; };
if raw.is_null() { if raw.is_null() {
Err(Error::FailedToInitialize) return Err(Error::FailedToInitialize);
} else {
Ok(Self {
raw,
color_format,
screen,
})
} }
}
/// Sets the screen to actually display the output of this render target
/// on the given [`Side`](gfx::Side).
pub fn set_output(&mut self, side: gfx::Side) {
let framebuf_format = self.screen.get_framebuffer_format();
// Set the render target to actually output to the given screen
let flags = transfer::Flags::default() let flags = transfer::Flags::default()
.in_format(self.color_format.into()) .in_format(color_format.into())
.out_format(ColorFormat::from(framebuf_format).into()); .out_format(color_format.into());
unsafe { unsafe {
citro3d_sys::C3D_RenderTargetSetOutput( citro3d_sys::C3D_RenderTargetSetOutput(
self.raw, raw,
self.screen.as_raw(), screen.as_raw(),
side.into(), screen.side().into(),
flags.bits(), flags.bits(),
); );
} }
Ok(Self {
raw,
_screen: screen,
})
} }
/// Clear the render target with the given 32-bit RGBA color and depth buffer value. /// Clear the render target with the given 32-bit RGBA color and depth buffer value.

Loading…
Cancel
Save