From 9aac807407b103a2a3530ce4fe93f6940920359b Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 29 Jan 2022 09:51:46 -0500 Subject: [PATCH] Address review comments Keep RawFrameBuffer alive as long as the Screen is, to ensure the Gfx is not dropped while the FrameBuffer is alive. --- ctru-rs/src/gfx.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/ctru-rs/src/gfx.rs b/ctru-rs/src/gfx.rs index 9a70199..c761549 100644 --- a/ctru-rs/src/gfx.rs +++ b/ctru-rs/src/gfx.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::default::Default; +use std::marker::PhantomData; use std::ops::Drop; use crate::services::gspgpu::{self, FramebufferFormat}; @@ -36,17 +37,19 @@ pub struct TopScreen; #[non_exhaustive] pub struct BottomScreen; -#[derive(Debug)] /// Representation of a framebuffer for one [`Side`] of the top screen, or the /// entire bottom screen. The inner pointer is only valid for one frame if double /// buffering is enabled. Data written to `ptr` will be rendered to the screen. -pub struct RawFrameBuffer { +#[derive(Debug)] +pub struct RawFrameBuffer<'screen> { /// Pointer to graphics data to be rendered. pub ptr: *mut u8, /// The width of the framebuffer in pixels. pub width: u16, /// The height of the framebuffer in pixels. pub height: u16, + /// Keep a mutable reference to the Screen for which this framebuffer is tied. + screen: PhantomData<&'screen mut dyn Screen>, } #[derive(Copy, Clone, Debug)] @@ -142,7 +145,7 @@ impl TopScreen { /// Note that the pointer of the framebuffer returned by this function can /// change after each call to this function if double buffering is enabled. pub fn get_raw_framebuffer(&mut self, side: Side) -> RawFrameBuffer { - RawFrameBuffer::for_screen_side(self.as_raw(), side.into()) + RawFrameBuffer::for_screen_side(self, side) } } @@ -152,17 +155,23 @@ impl BottomScreen { /// Note that the pointer of the framebuffer returned by this function can /// change after each call to this function if double buffering is enabled. pub fn get_raw_framebuffer(&mut self) -> RawFrameBuffer { - RawFrameBuffer::for_screen_side(self.as_raw(), Side::Left.into()) + RawFrameBuffer::for_screen_side(self, Side::Left) } } -impl RawFrameBuffer { - fn for_screen_side(screen: ctru_sys::gfxScreen_t, side: ctru_sys::gfx3dSide_t) -> Self { - let mut buf = RawFrameBuffer::default(); - unsafe { - buf.ptr = ctru_sys::gfxGetFramebuffer(screen, side, &mut buf.width, &mut buf.height); +impl<'screen> RawFrameBuffer<'screen> { + fn for_screen_side(screen: &'screen mut dyn Screen, side: Side) -> Self { + let mut width = 0; + let mut height = 0; + let ptr = unsafe { + ctru_sys::gfxGetFramebuffer(screen.as_raw(), side.into(), &mut width, &mut height) + }; + Self { + ptr, + width, + height, + screen: PhantomData, } - buf } } @@ -178,16 +187,6 @@ impl Screen for BottomScreen { } } -impl Default for RawFrameBuffer { - fn default() -> Self { - Self { - ptr: std::ptr::null_mut(), - width: 0, - height: 0, - } - } -} - impl From for ctru_sys::gfx3dSide_t { fn from(s: Side) -> ctru_sys::gfx3dSide_t { use self::Side::*;