Browse Source

Add a screen member to render::Target

This ensures the screen lives longer than the render target, and also
makes it a little more convenient to get the color format.
pull/4/head
Ian Chamberlain 2 years ago
parent
commit
1d35a44ede
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 12
      citro3d/examples/triangle.rs
  2. 29
      citro3d/src/lib.rs
  3. 42
      citro3d/src/render.rs

12
citro3d/examples/triangle.rs

@ -5,7 +5,7 @@ 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, ColorFormat, DepthFormat}; use citro3d::render::{ClearFlags, DepthFormat};
use std::ffi::CStr; use std::ffi::CStr;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
@ -62,15 +62,15 @@ fn main() {
let mut instance = citro3d::Instance::new().expect("failed to initialize Citro3D"); let mut instance = citro3d::Instance::new().expect("failed to initialize Citro3D");
let mut render_target = instance let mut render_target = citro3d::render::Target::new(
.render_target_for_screen( frame_buffer.width,
&frame_buffer, frame_buffer.height,
ColorFormat::RGBA8, &mut *top_screen,
DepthFormat::Depth24Stencil8, DepthFormat::Depth24Stencil8,
) )
.expect("failed to create render target"); .expect("failed to create render target");
render_target.set_output(&*top_screen, Side::Left); render_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();

29
citro3d/src/lib.rs

@ -7,11 +7,9 @@ pub mod texture;
pub mod vbo; pub mod vbo;
use citro3d_sys::C3D_FrameDrawOn; use citro3d_sys::C3D_FrameDrawOn;
use ctru::gfx::RawFrameBuffer; use ctru::gfx::Screen;
pub use error::{Error, Result}; pub use error::{Error, Result};
use render::Target;
/// 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
/// should instantiate to use this library. /// should instantiate to use this library.
#[non_exhaustive] #[non_exhaustive]
@ -41,32 +39,15 @@ impl Instance {
} }
} }
/// Create a default render target for the given screen.
///
/// # Errors
///
/// Fails if the render target could not be created.
pub fn render_target_for_screen(
&self,
frame_buffer: &RawFrameBuffer,
color_format: render::ColorFormat,
depth_format: render::DepthFormat,
) -> Result<Target> {
let _ = self;
Target::new(
frame_buffer.width.into(),
frame_buffer.height.into(),
color_format,
depth_format,
)
}
/// Select the given render target for drawing the frame. /// Select the given render target for drawing the frame.
/// ///
/// # 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(&mut self, target: &render::Target) -> Result<()> { pub fn select_render_target<'s, S: Screen>(
&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(())

42
citro3d/src/render.rs

@ -5,7 +5,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; use ctru::gfx::{self, Screen};
use ctru::services::gspgpu::FramebufferFormat; use ctru::services::gspgpu::FramebufferFormat;
use crate::{Error, Result}; use crate::{Error, Result};
@ -14,12 +14,13 @@ 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 { pub struct Target<'s, S> {
raw: *mut citro3d_sys::C3D_RenderTarget, raw: *mut citro3d_sys::C3D_RenderTarget,
color_format: ColorFormat, color_format: ColorFormat,
screen: &'s mut S,
} }
impl Drop for Target { impl<'s, S> Drop for Target<'s, S> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
C3D_RenderTargetDelete(self.raw); C3D_RenderTargetDelete(self.raw);
@ -27,24 +28,28 @@ impl Drop for Target {
} }
} }
impl Target { impl<'s, S> Target<'s, S>
where
S: '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.
/// ///
/// # Errors /// # Errors
/// ///
/// Fails if the specified sizes are invalid, or the target could not be /// Fails if the target could not be created.
/// created.
pub fn new( pub fn new(
width: u32, width: u16,
height: u32, height: u16,
color_format: ColorFormat, screen: &'s mut S,
depth_format: DepthFormat, depth_format: DepthFormat,
) -> Result<Self> { ) -> Result<Self> {
let color_format = screen.get_framebuffer_format().into();
let raw = unsafe { let raw = unsafe {
C3D_RenderTargetCreate( C3D_RenderTargetCreate(
width.try_into()?, width.into(),
height.try_into()?, height.into(),
color_format as GPU_COLORBUF, color_format as GPU_COLORBUF,
depth_format.as_raw(), depth_format.as_raw(),
) )
@ -53,13 +58,18 @@ impl Target {
if raw.is_null() { if raw.is_null() {
Err(Error::FailedToInitialize) Err(Error::FailedToInitialize)
} else { } else {
Ok(Self { raw, color_format }) Ok(Self {
raw,
color_format,
screen,
})
} }
} }
/// Sets the screen to actually display the output of this render target. /// Sets the screen to actually display the output of this render target
pub fn set_output(&mut self, screen: &impl gfx::Screen, side: gfx::Side) { /// on the given [`Side`](gfx::Side).
let framebuf_format = screen.get_framebuffer_format(); pub fn set_output(&mut self, side: gfx::Side) {
let framebuf_format = self.screen.get_framebuffer_format();
let flags = transfer::Flags::default() let flags = transfer::Flags::default()
.in_format(self.color_format.into()) .in_format(self.color_format.into())
@ -68,7 +78,7 @@ impl Target {
unsafe { unsafe {
citro3d_sys::C3D_RenderTargetSetOutput( citro3d_sys::C3D_RenderTargetSetOutput(
self.raw, self.raw,
screen.as_raw(), self.screen.as_raw(),
side.into(), side.into(),
flags.bits(), flags.bits(),
); );

Loading…
Cancel
Save