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. 18
      citro3d/examples/triangle.rs
  2. 29
      citro3d/src/lib.rs
  3. 42
      citro3d/src/render.rs

18
citro3d/examples/triangle.rs

@ -5,7 +5,7 @@ use ctru::services::apt::Apt; @@ -5,7 +5,7 @@ use ctru::services::apt::Apt;
use ctru::services::hid::{Hid, KeyPad};
use ctru::services::soc::Soc;
use citro3d::render::{ClearFlags, ColorFormat, DepthFormat};
use citro3d::render::{ClearFlags, DepthFormat};
use std::ffi::CStr;
use std::mem::MaybeUninit;
@ -62,15 +62,15 @@ fn main() { @@ -62,15 +62,15 @@ fn main() {
let mut instance = citro3d::Instance::new().expect("failed to initialize Citro3D");
let mut render_target = instance
.render_target_for_screen(
&frame_buffer,
ColorFormat::RGBA8,
DepthFormat::Depth24Stencil8,
)
.expect("failed to create render target");
let mut render_target = citro3d::render::Target::new(
frame_buffer.width,
frame_buffer.height,
&mut *top_screen,
DepthFormat::Depth24Stencil8,
)
.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 vertex_shader = shader.get(0).unwrap();

29
citro3d/src/lib.rs

@ -7,11 +7,9 @@ pub mod texture; @@ -7,11 +7,9 @@ pub mod texture;
pub mod vbo;
use citro3d_sys::C3D_FrameDrawOn;
use ctru::gfx::RawFrameBuffer;
use ctru::gfx::Screen;
pub use error::{Error, Result};
use render::Target;
/// The single instance for using `citro3d`. This is the base type that an application
/// should instantiate to use this library.
#[non_exhaustive]
@ -41,32 +39,15 @@ impl Instance { @@ -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.
///
/// # Errors
///
/// 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;
if unsafe { C3D_FrameDrawOn(target.as_raw()) } {
Ok(())

42
citro3d/src/render.rs

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

Loading…
Cancel
Save