Browse Source

Merge branch 'main' into render-target-screen-lifetime

pull/4/head
Ian Chamberlain 2 years ago
parent
commit
b699208f8e
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 2
      Cargo.toml
  2. 8
      bindgen-citro3d/Cargo.toml
  3. 92
      bindgen-citro3d/src/main.rs
  4. 1
      citro3d-sys/Cargo.toml
  5. 42
      citro3d-sys/bindgen.sh
  6. 1244
      citro3d-sys/src/bindings.rs
  7. 2
      citro3d-sys/src/gx.rs
  8. 1
      citro3d-sys/src/texenv.rs
  9. 4
      citro3d-sys/src/uniforms.rs
  10. 3
      citro3d/Cargo.toml
  11. 18
      citro3d/examples/triangle.rs
  12. 4
      citro3d/src/lib.rs
  13. 20
      citro3d/src/render.rs
  14. 13
      citro3d/src/render/transfer.rs
  15. 24
      citro3d/src/shader.rs

2
Cargo.toml

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
[workspace]
members = ["citro3d-sys", "citro3d"]
members = ["citro3d-sys", "citro3d", "bindgen-citro3d"]
[patch."https://github.com/rust3ds/citro3d-rs.git"]
citro3d-sys = { path = "citro3d-sys" }

8
bindgen-citro3d/Cargo.toml

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
[package]
name = "bindgen-citro3d"
version = "0.1.0"
edition = "2021"
description = "Helper tool to generate citro3d-sys bindings."
[dependencies]
bindgen = "0.62.0"

92
bindgen-citro3d/src/main.rs

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
//! This is meant to be run as a "script" to generate bindings to `citro3d`.
//! We use this instead of `bindgen-cli` to enable the use of [`CustomCallbacks`]
//! with [`bindgen`] as a library for finer grained control of the bindings.
use std::iter::FromIterator;
use std::path::PathBuf;
use bindgen::callbacks::{DeriveTrait, ImplementsTrait, ParseCallbacks};
use bindgen::{Builder, RustTarget};
fn main() {
let devkitpro = std::env::var("DEVKITPRO").expect("DEVKITPRO not set in environment");
let devkitarm = std::env::var("DEVKITARM").expect("DEVKITARM not set in environment");
let include_path = PathBuf::from_iter([devkitpro.as_str(), "libctru", "include"]);
let header = include_path.join("tex3ds.h");
let sysroot = PathBuf::from(devkitarm).join("arm-none-eabi");
let system_include = sysroot.join("include");
let bindings = Builder::default()
.header(header.to_str().unwrap())
.rust_target(RustTarget::Nightly)
.use_core()
.trust_clang_mangling(false)
.layout_tests(false)
.ctypes_prefix("::libc")
.prepend_enum_name(false)
.fit_macro_constants(true)
.raw_line("use ctru_sys::*;")
.must_use_type("Result")
.blocklist_type("u(8|16|32|64)")
.opaque_type("(GPU|GFX)_.*")
.opaque_type("float24Uniform_s")
.allowlist_file(".*/c3d/.*[.]h")
.allowlist_file(".*/tex3ds[.]h")
.blocklist_file(".*/3ds/.*[.]h")
.blocklist_file(".*/sys/.*[.]h")
.clang_args([
"--target=arm-none-eabi",
"--sysroot",
sysroot.to_str().unwrap(),
"-isystem",
system_include.to_str().unwrap(),
"-I",
include_path.to_str().unwrap(),
"-mfloat-abi=hard",
"-march=armv6k",
"-mtune=mpcore",
"-mfpu=vfp",
"-DARM11 ",
"-D_3DS ",
"-D__3DS__ ",
])
.parse_callbacks(Box::new(CustomCallbacks))
.generate()
.expect("Unable to generate bindings");
bindings
.write(Box::new(std::io::stdout()))
.expect("failed to write bindings");
}
/// Custom callback struct to allow us to mark some "known good types" as
/// [`Copy`], which in turn allows using Rust `union` instead of bindgen union
/// types. See
/// <https://rust-lang.github.io/rust-bindgen/using-unions.html#which-union-type-will-bindgen-generate>
/// for more info.
///
/// We do the same for [`Debug`] just for the convenience of derived Debug impls
/// on some `citro3d` types.
#[derive(Debug)]
struct CustomCallbacks;
impl ParseCallbacks for CustomCallbacks {
fn blocklisted_type_implements_trait(
&self,
name: &str,
derive_trait: DeriveTrait,
) -> Option<ImplementsTrait> {
if let DeriveTrait::Copy | DeriveTrait::Debug = derive_trait {
match name {
"u64_" | "u32_" | "u16_" | "u8_" | "u64" | "u32" | "u16" | "u8" | "gfxScreen_t"
| "gfx3dSide_t" => Some(ImplementsTrait::Yes),
_ if name.starts_with("GPU_") => Some(ImplementsTrait::Yes),
_ => None,
}
} else {
None
}
}
}

1
citro3d-sys/Cargo.toml

@ -6,3 +6,4 @@ edition = "2021" @@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
libc = "0.2.116"
ctru-sys = { git = "https://github.com/rust3ds/ctru-rs.git" }

42
citro3d-sys/bindgen.sh

@ -2,44 +2,4 @@ @@ -2,44 +2,4 @@
set -euxo pipefail
bindgen "$DEVKITPRO/libctru/include/citro3d.h" \
--rust-target nightly \
--use-core \
--distrust-clang-mangling \
--no-layout-tests \
--ctypes-prefix "::libc" \
--no-prepend-enum-name \
--fit-macro-constant-types \
--must-use-type "Result" \
--generate "functions,types,vars" \
--blocklist-type "u(8|16|32|64)" \
--opaque-type "GPU_.*" \
--opaque-type "GFX_.*" \
--opaque-type "float24Uniform_s" \
--allowlist-type "C3D_.*" \
--allowlist-type "DVLB_.*" \
--allowlist-type "shader.*" \
--allowlist-type "float24Uniform_s" \
--allowlist-function "C3D_.*" \
--allowlist-function "shader.*" \
--allowlist-function "DVLB_.*" \
--allowlist-function "linear.*" \
--allowlist-var "C3D_.*" \
--allowlist-type "GPU_.*" \
--allowlist-type "GX_.*" \
--allowlist-function 'AttrInfo_(Init|AddLoader|AddFixed)' \
--allowlist-function 'BufInfo_(Init|Add)' \
--allowlist-function 'Mtx_.*' \
-- \
--target=arm-none-eabi \
--sysroot=$DEVKITARM/arm-none-eabi \
-isystem$DEVKITARM/arm-none-eabi/include \
-I$DEVKITPRO/libctru/include \
-mfloat-abi=hard \
-march=armv6k \
-mtune=mpcore \
-mfpu=vfp \
-DARM11 \
-D_3DS \
-D__3DS__ \
> src/bindings.rs
cargo run --package bindgen-citro3d > src/bindings.rs

1244
citro3d-sys/src/bindings.rs

File diff suppressed because it is too large Load Diff

2
citro3d-sys/src/gx.rs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//! Helper functions based on `<3ds/gpu/gx.h>`.
use crate::{GX_TRANSFER_FORMAT, GX_TRANSFER_SCALE};
use ctru_sys::{GX_TRANSFER_FORMAT, GX_TRANSFER_SCALE};
#[inline]
pub fn GX_TRANSFER_FLIP_VERT(flip: bool) -> u32 {

1
citro3d-sys/src/texenv.rs

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
use core::ops::{BitOr, Shl};
use ctru_sys::{GPU_COMBINEFUNC, GPU_PREVIOUS, GPU_REPLACE, GPU_TEVSCALE_1, GPU_TEVSRC};
use libc::c_int;
use super::*;

4
citro3d-sys/src/uniforms.rs

@ -1,6 +1,8 @@ @@ -1,6 +1,8 @@
//! Definitions from`<c3d/uniforms.h>`
use super::{C3D_FVUnif, C3D_FVUnifDirty, C3D_FVec, C3D_Mtx, GPU_SHADER_TYPE};
use ctru_sys::GPU_SHADER_TYPE;
use super::{C3D_FVUnif, C3D_FVUnifDirty, C3D_FVec, C3D_Mtx};
#[inline]
pub unsafe fn C3D_FVUnifWritePtr(

3
citro3d/Cargo.toml

@ -8,6 +8,5 @@ bitflags = "1.3.2" @@ -8,6 +8,5 @@ bitflags = "1.3.2"
bytemuck = { version = "1.10.0", features = ["extern_crate_std"] }
citro3d-sys = { git = "https://github.com/rust3ds/citro3d-rs.git" }
ctru-rs = { git = "https://github.com/rust3ds/ctru-rs.git" }
ctru-sys = { git = "https://github.com/rust3ds/ctru-rs.git" }
libc = "0.2.125"
[dev-dependencies]

18
citro3d/examples/triangle.rs

@ -112,7 +112,7 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void) @@ -112,7 +112,7 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void)
// Get the location of the uniforms
let projection_name = CStr::from_bytes_with_nul(b"projection\0").unwrap();
let uloc_projection = citro3d_sys::shaderInstanceGetUniformLocation(
let uloc_projection = ctru_sys::shaderInstanceGetUniformLocation(
(*program.as_raw()).vertexShader,
projection_name.as_ptr(),
);
@ -120,8 +120,8 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void) @@ -120,8 +120,8 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void)
// Configure attributes for use with the vertex shader
let attr_info = citro3d_sys::C3D_GetAttrInfo();
citro3d_sys::AttrInfo_Init(attr_info);
citro3d_sys::AttrInfo_AddLoader(attr_info, 0, citro3d_sys::GPU_FLOAT, 3); // v0=position
citro3d_sys::AttrInfo_AddLoader(attr_info, 1, citro3d_sys::GPU_FLOAT, 3); // v1=color
citro3d_sys::AttrInfo_AddLoader(attr_info, 0, ctru_sys::GPU_FLOAT, 3); // v0=position
citro3d_sys::AttrInfo_AddLoader(attr_info, 1, ctru_sys::GPU_FLOAT, 3); // v1=color
// Compute the projection matrix
let projection = {
@ -141,7 +141,7 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void) @@ -141,7 +141,7 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void)
};
// Create the vertex buffer object
let vbo_data: *mut Vertex = citro3d_sys::linearAlloc(
let vbo_data: *mut Vertex = ctru_sys::linearAlloc(
std::mem::size_of_val(VERTICES)
.try_into()
.expect("size fits in u32"),
@ -170,11 +170,11 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void) @@ -170,11 +170,11 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void)
citro3d_sys::C3D_TexEnvSrc(
env,
citro3d_sys::C3D_Both,
citro3d_sys::GPU_PRIMARY_COLOR,
ctru_sys::GPU_PRIMARY_COLOR,
0,
0,
);
citro3d_sys::C3D_TexEnvFunc(env, citro3d_sys::C3D_Both, citro3d_sys::GPU_REPLACE);
citro3d_sys::C3D_TexEnvFunc(env, citro3d_sys::C3D_Both, ctru_sys::GPU_REPLACE);
(uloc_projection, projection, vbo_data.cast())
}
@ -183,11 +183,11 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void) @@ -183,11 +183,11 @@ fn scene_init(program: &mut shader::Program) -> (i8, C3D_Mtx, *mut libc::c_void)
fn scene_render(uloc_projection: i32, projection: &C3D_Mtx) {
unsafe {
// Update the uniforms
citro3d_sys::C3D_FVUnifMtx4x4(citro3d_sys::GPU_VERTEX_SHADER, uloc_projection, projection);
citro3d_sys::C3D_FVUnifMtx4x4(ctru_sys::GPU_VERTEX_SHADER, uloc_projection, projection);
// Draw the VBO
citro3d_sys::C3D_DrawArrays(
citro3d_sys::GPU_TRIANGLES,
ctru_sys::GPU_TRIANGLES,
0,
VERTICES
.len()
@ -199,6 +199,6 @@ fn scene_render(uloc_projection: i32, projection: &C3D_Mtx) { @@ -199,6 +199,6 @@ fn scene_render(uloc_projection: i32, projection: &C3D_Mtx) {
fn scene_exit(vbo_data: *mut libc::c_void) {
unsafe {
citro3d_sys::linearFree(vbo_data);
ctru_sys::linearFree(vbo_data);
}
}

4
citro3d/src/lib.rs

@ -22,7 +22,7 @@ impl Instance { @@ -22,7 +22,7 @@ impl Instance {
///
/// Fails if `citro3d` cannot be initialized.
pub fn new() -> Result<Self> {
Self::with_cmdbuf_size(citro3d_sys::C3D_DEFAULT_CMDBUF_SIZE)
Self::with_cmdbuf_size(citro3d_sys::C3D_DEFAULT_CMDBUF_SIZE.try_into().unwrap())
}
/// Initialize the instance with a specified command buffer size.
@ -30,7 +30,7 @@ impl Instance { @@ -30,7 +30,7 @@ impl Instance {
/// # Errors
///
/// Fails if `citro3d` cannot be initialized.
pub fn with_cmdbuf_size(size: u32) -> Result<Self> {
pub fn with_cmdbuf_size(size: usize) -> Result<Self> {
if unsafe { citro3d_sys::C3D_Init(size) } {
Ok(Self)
} else {

20
citro3d/src/render.rs

@ -4,11 +4,11 @@ @@ -4,11 +4,11 @@
use std::cell::RefMut;
use citro3d_sys::{
C3D_RenderTarget, C3D_RenderTargetCreate, C3D_RenderTargetDelete, C3D_DEPTHTYPE, GPU_COLORBUF,
GPU_DEPTHBUF,
C3D_RenderTarget, C3D_RenderTargetCreate, C3D_RenderTargetDelete, C3D_DEPTHTYPE,
};
use ctru::gfx::Screen;
use ctru::services::gspgpu::FramebufferFormat;
use ctru_sys::{GPU_COLORBUF, GPU_DEPTHBUF};
use crate::{Error, Result};
@ -108,15 +108,15 @@ bitflags::bitflags! { @@ -108,15 +108,15 @@ bitflags::bitflags! {
#[derive(Clone, Copy, Debug)]
pub enum ColorFormat {
/// 8-bit Red + 8-bit Green + 8-bit Blue + 8-bit Alpha.
RGBA8 = citro3d_sys::GPU_RB_RGBA8,
RGBA8 = ctru_sys::GPU_RB_RGBA8,
/// 8-bit Red + 8-bit Green + 8-bit Blue.
RGB8 = citro3d_sys::GPU_RB_RGB8,
RGB8 = ctru_sys::GPU_RB_RGB8,
/// 5-bit Red + 5-bit Green + 5-bit Blue + 1-bit Alpha.
RGBA5551 = citro3d_sys::GPU_RB_RGBA5551,
RGBA5551 = ctru_sys::GPU_RB_RGBA5551,
/// 5-bit Red + 6-bit Green + 5-bit Blue.
RGB565 = citro3d_sys::GPU_RB_RGB565,
RGB565 = ctru_sys::GPU_RB_RGB565,
/// 4-bit Red + 4-bit Green + 4-bit Blue + 4-bit Alpha.
RGBA4 = citro3d_sys::GPU_RB_RGBA4,
RGBA4 = ctru_sys::GPU_RB_RGBA4,
}
impl From<FramebufferFormat> for ColorFormat {
@ -137,11 +137,11 @@ impl From<FramebufferFormat> for ColorFormat { @@ -137,11 +137,11 @@ impl From<FramebufferFormat> for ColorFormat {
#[derive(Clone, Copy, Debug)]
pub enum DepthFormat {
/// 16-bit depth.
Depth16 = citro3d_sys::GPU_RB_DEPTH16,
Depth16 = ctru_sys::GPU_RB_DEPTH16,
/// 24-bit depth.
Depth24 = citro3d_sys::GPU_RB_DEPTH24,
Depth24 = ctru_sys::GPU_RB_DEPTH24,
/// 24-bit depth + 8-bit Stencil.
Depth24Stencil8 = citro3d_sys::GPU_RB_DEPTH24_STENCIL8,
Depth24Stencil8 = ctru_sys::GPU_RB_DEPTH24_STENCIL8,
}
impl DepthFormat {

13
citro3d/src/render/transfer.rs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
use citro3d_sys::{GX_TRANSFER_FORMAT, GX_TRANSFER_IN_FORMAT, GX_TRANSFER_OUT_FORMAT};
use citro3d_sys::{GX_TRANSFER_IN_FORMAT, GX_TRANSFER_OUT_FORMAT};
use ctru_sys::GX_TRANSFER_FORMAT;
use super::ColorFormat;
@ -33,15 +34,15 @@ impl Flags { @@ -33,15 +34,15 @@ impl Flags {
#[repr(u32)]
pub enum Format {
/// 8-bit Red + 8-bit Green + 8-bit Blue + 8-bit Alpha.
RGBA8 = citro3d_sys::GX_TRANSFER_FMT_RGBA8,
RGBA8 = ctru_sys::GX_TRANSFER_FMT_RGBA8,
/// 8-bit Red + 8-bit Green + 8-bit Blue.
RGB8 = citro3d_sys::GX_TRANSFER_FMT_RGB8,
RGB8 = ctru_sys::GX_TRANSFER_FMT_RGB8,
/// 5-bit Red + 5-bit Green + 5-bit Blue + 1-bit Alpha.
RGB565 = citro3d_sys::GX_TRANSFER_FMT_RGB565,
RGB565 = ctru_sys::GX_TRANSFER_FMT_RGB565,
/// 5-bit Red + 6-bit Green + 5-bit Blue.
RGB5A1 = citro3d_sys::GX_TRANSFER_FMT_RGB5A1,
RGB5A1 = ctru_sys::GX_TRANSFER_FMT_RGB5A1,
/// 4-bit Red + 4-bit Green + 4-bit Blue + 4-bit Alpha.
RGBA4 = citro3d_sys::GX_TRANSFER_FMT_RGBA4,
RGBA4 = ctru_sys::GX_TRANSFER_FMT_RGBA4,
}
impl From<ColorFormat> for Format {

24
citro3d/src/shader.rs

@ -16,7 +16,7 @@ pub mod macros; @@ -16,7 +16,7 @@ pub mod macros;
///
/// The PICA200 does not support user-programmable fragment shaders.
pub struct Program {
program: citro3d_sys::shaderProgram_s,
program: ctru_sys::shaderProgram_s,
}
impl Program {
@ -30,14 +30,14 @@ impl Program { @@ -30,14 +30,14 @@ impl Program {
pub fn new(vertex_shader: Entrypoint) -> Result<Self, ctru::Error> {
let mut program = unsafe {
let mut program = MaybeUninit::uninit();
let result = citro3d_sys::shaderProgramInit(program.as_mut_ptr());
let result = ctru_sys::shaderProgramInit(program.as_mut_ptr());
if result != 0 {
return Err(ctru::Error::from(result));
}
program.assume_init()
};
let ret = unsafe { citro3d_sys::shaderProgramSetVsh(&mut program, vertex_shader.as_raw()) };
let ret = unsafe { ctru_sys::shaderProgramSetVsh(&mut program, vertex_shader.as_raw()) };
if ret == 0 {
Ok(Self { program })
@ -58,7 +58,7 @@ impl Program { @@ -58,7 +58,7 @@ impl Program {
stride: u8,
) -> Result<(), ctru::Error> {
let ret = unsafe {
citro3d_sys::shaderProgramSetGsh(&mut self.program, geometry_shader.as_raw(), stride)
ctru_sys::shaderProgramSetGsh(&mut self.program, geometry_shader.as_raw(), stride)
};
if ret == 0 {
@ -69,7 +69,7 @@ impl Program { @@ -69,7 +69,7 @@ impl Program {
}
// TODO: pub(crate)
pub fn as_raw(&mut self) -> *mut citro3d_sys::shaderProgram_s {
pub fn as_raw(&mut self) -> *mut ctru_sys::shaderProgram_s {
&mut self.program
}
}
@ -77,7 +77,7 @@ impl Program { @@ -77,7 +77,7 @@ impl Program {
impl Drop for Program {
fn drop(&mut self) {
unsafe {
let _ = citro3d_sys::shaderProgramFree(self.as_raw());
let _ = ctru_sys::shaderProgramFree(self.as_raw());
}
}
}
@ -88,7 +88,7 @@ impl Drop for Program { @@ -88,7 +88,7 @@ impl Drop for Program {
///
/// This is the result of parsing a shader binary (shbin), and the resulting
/// [`Entrypoint`]s can be used as part of a [`Program`].
pub struct Library(*mut citro3d_sys::DVLB_s);
pub struct Library(*mut ctru_sys::DVLB_s);
impl Library {
/// Parse a new shader library from input bytes.
@ -100,7 +100,7 @@ impl Library { @@ -100,7 +100,7 @@ impl Library {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Box<dyn Error>> {
let aligned: &[u32] = bytemuck::try_cast_slice(bytes)?;
Ok(Self(unsafe {
citro3d_sys::DVLB_ParseFile(
ctru_sys::DVLB_ParseFile(
// SAFETY: we're trusting the parse implementation doesn't mutate
// the contents of the data. From a quick read it looks like that's
// correct and it should just take a const arg in the API.
@ -132,7 +132,7 @@ impl Library { @@ -132,7 +132,7 @@ impl Library {
self.len() == 0
}
fn as_raw(&mut self) -> *mut citro3d_sys::DVLB_s {
fn as_raw(&mut self) -> *mut ctru_sys::DVLB_s {
self.0
}
}
@ -140,7 +140,7 @@ impl Library { @@ -140,7 +140,7 @@ impl Library {
impl Drop for Library {
fn drop(&mut self) {
unsafe {
citro3d_sys::DVLB_Free(self.as_raw());
ctru_sys::DVLB_Free(self.as_raw());
}
}
}
@ -149,12 +149,12 @@ impl Drop for Library { @@ -149,12 +149,12 @@ impl Drop for Library {
/// vertex or a geometry shader.
#[derive(Clone, Copy)]
pub struct Entrypoint<'lib> {
ptr: *mut citro3d_sys::DVLE_s,
ptr: *mut ctru_sys::DVLE_s,
_library: &'lib Library,
}
impl<'lib> Entrypoint<'lib> {
fn as_raw(self) -> *mut citro3d_sys::DVLE_s {
fn as_raw(self) -> *mut ctru_sys::DVLE_s {
self.ptr
}
}

Loading…
Cancel
Save