Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 82 additions & 26 deletions src/gpu.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
//! Graphics and GPU support and utils

use ::alloc::boxed::Box;
use ::alloc::sync::Arc;

use crate::ipc::sf;
use crate::mem::{alloc, wait_for_permission};
use crate::result::*;
use crate::service;
use crate::service::applet;

Check warning on line 9 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
use crate::service::dispdrv;
use crate::service::nv;
use crate::service::nv::INvDrvClient;
use crate::service::nv::{ErrorCode, Fd,INvDrvClient, IoctlId};
use crate::service::vi;
use crate::service::vi::{
ApplicationDisplayRootService, IApplicationDisplayClient, ManagerDisplayRootService,
ApplicationDisplayRootService, ApplicationDisplay, IApplicationDisplayClient, ManagerDisplayRootService,
SystemDisplayRootService,
};
use crate::svc;
Expand Down Expand Up @@ -928,19 +927,76 @@
}

/// A holder for our `*RootService` objects, just to keep them alive for the lifetime of the `Context`
#[allow(missing_docs)]
pub enum RootServiceHolder {
/// Application Service
Application(ApplicationDisplayRootService),
/// Manager Service
Manager(ManagerDisplayRootService),
/// System Service
System(SystemDisplayRootService),
}

/// A holder for our `nvdrv` service objects
pub enum NvDrvServiceHolder {
/// Application Service
Application(nv::ApplicationNvDrvService),
/// Applet Service

Check warning on line 943 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
Applet(nv::AppletNvDrvService),
/// System Service
System(nv::SystemNvDrvService)
}

impl NvDrvServiceHolder {
fn open(&self, path: sf::InMapAliasBuffer<'_, u8>) -> Result<(Fd, ErrorCode)> {
match self {

Check warning on line 951 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
Self::Application(s) => s.open(path),
Self::Applet(s) => s.open(path),
Self::System(s) => s.open(path)
}
}
fn ioctl(&self, fd: Fd, id: IoctlId, in_buf: sf::InOutAutoSelectBuffer<'_, u8>) -> Result<ErrorCode> {
match self {
Self::Application(s) => s.ioctl(fd, id, in_buf),
Self::Applet(s) => s.ioctl(fd, id, in_buf),
Self::System(s) => s.ioctl(fd, id, in_buf)

Check warning on line 961 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
}
}
fn close(&self, fd: Fd) -> Result<ErrorCode> {
match self {

Check warning on line 965 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
Self::Application(s) => s.close(fd),
Self::Applet(s) => s.close(fd),
Self::System(s) => s.close(fd)
}
}
fn initialize(
&self,
transfer_mem_size: u32,
self_process_handle: sf::CopyHandle,
transfer_mem_handle: sf::CopyHandle,

Check warning on line 975 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
) -> Result<ErrorCode> {
match self {
Self::Application(s) => s.initialize(transfer_mem_size, self_process_handle, transfer_mem_handle),
Self::Applet(s) => s.initialize(transfer_mem_size, self_process_handle, transfer_mem_handle),
Self::System(s) => s.initialize(transfer_mem_size, self_process_handle, transfer_mem_handle)
}
}

fn close_self(&mut self) {
use crate::ipc::client::IClientObject;
match self {

Check warning on line 986 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
Self::Application(s) => s.get_session_mut().close(),
Self::Applet(s) => s.get_session_mut().close(),
Self::System(s) => s.get_session_mut().close()
}
}
}

/// Represents a graphics context
#[allow(dead_code)]
pub struct Context {
vi_service: RootServiceHolder,
nvdrv_service: Box<dyn INvDrvClient>,
application_display_service: Box<dyn IApplicationDisplayClient>,
nvdrv_service: NvDrvServiceHolder,
application_display_service: ApplicationDisplay,
hos_binder_driver: Arc<dispdrv::HOSBinderDriver>,
transfer_mem: alloc::Buffer<u8>,
transfer_mem_handle: svc::Handle,
Expand Down Expand Up @@ -969,37 +1025,37 @@
use vi::IManagerDisplayRootClient;
let vi_srv = service::new_service_object::<ManagerDisplayRootService>()?;
let app_disp_srv =
Box::new(vi_srv.get_display_service(vi::DisplayServiceMode::Privileged)?);
vi_srv.get_display_service(vi::DisplayServiceMode::Privileged)?;

(RootServiceHolder::Manager(vi_srv), app_disp_srv)
}
ViServiceKind::System => {
use vi::ISystemDisplayRootClient;
let vi_srv = service::new_service_object::<SystemDisplayRootService>()?;
let app_disp_srv =
Box::new(vi_srv.get_display_service(vi::DisplayServiceMode::Privileged)?);
vi_srv.get_display_service(vi::DisplayServiceMode::Privileged)?;

(RootServiceHolder::System(vi_srv), app_disp_srv)
}
ViServiceKind::Application => {

Check warning on line 1040 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
use vi::IApplicationDisplayRootClient;
let vi_srv = service::new_service_object::<ApplicationDisplayRootService>()?;
let app_disp_srv =
Box::new(vi_srv.get_display_service(vi::DisplayServiceMode::User)?);
vi_srv.get_display_service(vi::DisplayServiceMode::User)?;

(RootServiceHolder::Application(vi_srv), app_disp_srv)
}
};

Check warning on line 1048 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs

let nvdrv_srv: Box<dyn INvDrvClient> = match nv_kind {
let nvdrv_srv= match nv_kind {
NvDrvServiceKind::Application => {
Box::new(service::new_service_object::<nv::ApplicationNvDrvService>()?)
NvDrvServiceHolder::Application(service::new_service_object::<nv::ApplicationNvDrvService>()?)
}
NvDrvServiceKind::Applet => {
Box::new(service::new_service_object::<nv::AppletNvDrvService>()?)
NvDrvServiceHolder::Applet(service::new_service_object::<nv::AppletNvDrvService>()?)
}
NvDrvServiceKind::System => {
Box::new(service::new_service_object::<nv::SystemNvDrvService>()?)
NvDrvServiceHolder::System(service::new_service_object::<nv::SystemNvDrvService>()?)
}
};

Expand All @@ -1023,10 +1079,10 @@
/// * `nvdrv_srv`: The NV [`INvDrvClient`] service object
/// * `transfer_mem_size`: The transfer memory size to use
/// * `nv_host_as_gpu`: Flag whether to open a handle to the GPU for hardware accelerated rendering.
pub fn from(
fn from(
vi_srv: RootServiceHolder,
application_display_srv: Box<dyn vi::IApplicationDisplayClient>,
mut nvdrv_srv: Box<dyn INvDrvClient>,
application_display_srv: ApplicationDisplay,
mut nvdrv_srv: NvDrvServiceHolder,
transfer_mem_size: usize,
nv_host_as_gpu: bool,
) -> Result<Self> {
Expand Down Expand Up @@ -1074,7 +1130,7 @@
let _ = nvdrv_srv.close(nvhostctrl_fd);

let _ = nvdrv_srv.close(transfer_mem_handle);
nvdrv_srv.get_session_mut().close();
nvdrv_srv.close_self();
svc::close_handle(transfer_mem_handle).unwrap();
let _ = wait_for_permission(transfer_mem.ptr, MemoryPermission::Write(), None);
return Err(rc);
Expand All @@ -1094,26 +1150,26 @@
})
}

/// Gets the underlying NV [`INvDrvClient`] service object
pub fn nvdrv_service(&self) -> &dyn INvDrvClient {
self.nvdrv_service.as_ref()
/// Gets the wrapped NV [`INvDrvClient`] service object
pub fn nvdrv_service(&self) -> &NvDrvServiceHolder {
&self.nvdrv_service
}

/// Gets the underlying NV [`INvDrvClient`] service object mutably
pub fn nvdrv_service_mut(&mut self) -> &mut dyn INvDrvClient {
self.nvdrv_service.as_mut()
/// Gets the wrapped NV [`INvDrvClient`] service object mutably
pub fn nvdrv_service_mut(&mut self) -> &mut NvDrvServiceHolder {
&mut self.nvdrv_service
}

Check warning on line 1162 in src/gpu.rs

View workflow job for this annotation

GitHub Actions / format

Diff in /home/runner/work/nx/nx/src/gpu.rs
/// Gets the underlying [`IApplicationDisplayClient`] object
pub fn get_application_display_service(&self) -> &dyn vi::IApplicationDisplayClient {
self.application_display_service.as_ref()
& self.application_display_service
}

/// Gets the underlying [`IApplicationDisplayClient`] object mutably
pub fn get_application_display_service_mut(
&mut self,
) -> &mut dyn vi::IApplicationDisplayClient {
self.application_display_service.as_mut()
&mut self.application_display_service
}

/// Gets the underlying [`IHOSBinderDriverClient`][`dispdrv::IHOSBinderDriverClient`] object
Expand All @@ -1131,7 +1187,7 @@
self.nvdrv_service.close(self.nvhostctrl_fd);

self.nvdrv_service.close(self.transfer_mem_handle);
self.nvdrv_service.get_session_mut().close();
self.nvdrv_service.close_self();
svc::close_handle(self.transfer_mem_handle).unwrap();
wait_for_permission(self.transfer_mem.ptr, MemoryPermission::Write(), None);
}
Expand Down
93 changes: 51 additions & 42 deletions src/gpu/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ impl Surface {
)?;
let mut parcel = parcel::Parcel::new();
parcel.load_from(native_window);
let binder_handle = parcel.read::<parcel::ParcelData>()?.handle;
let binder_handle = parcel
.read::<parcel::ParcelData>()
.expect("ParcelData should always be readable if create_stray_layer succeeds.")
.handle;
(binder_handle, layer_id)
};

Expand Down Expand Up @@ -164,51 +167,57 @@ impl Surface {
sf::Buffer::from_other_mut_var(&mut native_window),
)?;

let mut binder_parcel = parcel::Parcel::new();
binder_parcel.load_from(native_window);
let binder_handle = binder_parcel.read::<parcel::ParcelData>()?.handle;

match scaling {
ScaleMode::None => {
system_display_service.set_layer_size(
layer_id,
framebuffer_width as u64,
framebuffer_height as u64,
)?;
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::FitToLayer, layer_id)?
let binder_handle = match try {
let mut binder_parcel = parcel::Parcel::new();
binder_parcel.load_from(native_window);
let binder_handle = binder_parcel.read::<parcel::ParcelData>()?.handle;
match scaling {
ScaleMode::None => {
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::None, layer_id)?;
system_display_service.set_layer_size(
layer_id,
framebuffer_width as u64,
framebuffer_height as u64,
)?;
}
ScaleMode::FitToLayer { width, height } => {
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::FitToLayer, layer_id)?;
system_display_service.set_layer_size(layer_id, width as u64, height as u64)?;
}
ScaleMode::PreseveAspect { height } => {
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::PreserveAspectRatio, layer_id)?;
system_display_service.set_layer_size(
layer_id,
(framebuffer_width as f32 * (height as f32) / (framebuffer_height as f32))
as u64,
height as u64,
)?;
}
}
ScaleMode::FitToLayer { width, height } => {
system_display_service.set_layer_size(layer_id, width as u64, height as u64)?;
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::FitToLayer, layer_id)?;
}
ScaleMode::PreseveAspect { height } => {
system_display_service.set_layer_size(
layer_id,
(framebuffer_width as f32 * (height as f32) / (framebuffer_height as f32))
as u64,
height as u64,
)?;
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::PreserveAspectRatio, layer_id)?;
}
}
gpu_guard
.application_display_service
.set_scaling_mode(vi::ScalingMode::FitToLayer, layer_id)?;

system_display_service.set_layer_position(x, y, layer_id)?;
system_display_service.set_layer_position(x, y, layer_id)?;

let z_value = match z {
LayerZ::Max => system_display_service.get_z_order_count_max(display_id)?,
LayerZ::Min => system_display_service.get_z_order_count_min(display_id)?,
LayerZ::Value(z_val) => z_val,
};
system_display_service.set_layer_z(layer_id, z_value)?;

let z_value = match z {
LayerZ::Max => system_display_service.get_z_order_count_max(display_id)?,
LayerZ::Min => system_display_service.get_z_order_count_min(display_id)?,
LayerZ::Value(z_val) => z_val,
binder_handle
} {
Err(e) => {
manager_display_service.destroy_managed_layer(layer_id)?;
return Err(e);
}
Ok(handle) => handle,
};
system_display_service.set_layer_z(layer_id, z_value)?;

drop(gpu_guard);
Self::new_from_parts(
Expand Down
8 changes: 4 additions & 4 deletions src/hbl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,11 @@ pub static G_NEXT_LOAD_PATH: Mutex<Option<&'static mut ArrayString<512>>> = Mute
pub static G_NEXT_LOAD_ARGV: Mutex<Option<&'static mut ArrayString<2048>>> = Mutex::new(None);

pub(crate) fn set_next_load_entry_ptr(
next_load_path: &'static mut ArrayString<512>,
next_load_argv: &'static mut ArrayString<2048>,
next_load_path: Option<&'static mut ArrayString<512>>,
next_load_argv: Option<&'static mut ArrayString<2048>>,
) {
*G_NEXT_LOAD_PATH.lock() = Some(next_load_path);
*G_NEXT_LOAD_ARGV.lock() = Some(next_load_argv);
*G_NEXT_LOAD_PATH.lock() = next_load_path;
*G_NEXT_LOAD_ARGV.lock() = next_load_argv;
}

/// Gets the next load path, AKA the path of the homebrew NRO which will be executed after this one exits
Expand Down
19 changes: 11 additions & 8 deletions src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,10 @@ impl BufferDescriptor {
}

pub fn new(buffer: *const u8, buffer_size: usize, flags: BufferFlags) -> Self {
let address_low = buffer as usize as u32;
let address_mid = ((buffer as usize) >> 32) as u32;
let address_high = ((buffer as usize) >> 36) as u32;
let buffer = buffer.expose_provenance();
let address_low = buffer as u32;
let address_mid = (buffer >> 32) as u32;
let address_high = (buffer >> 36) as u32;
let size_low = buffer_size as u32;
let size_high = (buffer_size >> 32) as u32;

Expand Down Expand Up @@ -171,9 +172,10 @@ impl SendStaticDescriptor {
}

pub fn new(buffer: *const u8, buffer_size: usize, index: u32) -> Self {
let address_low = buffer as usize as u32;
let address_mid = ((buffer as usize) >> 32) as u32;
let address_high = ((buffer as usize) >> 36) as u32;
let buffer = buffer.expose_provenance();
let address_low = buffer as u32;
let address_mid = (buffer >> 32) as u32;
let address_high = (buffer >> 36) as u32;

let mut bits: u32 = 0;
write_bits!(0, 5, bits, index);
Expand Down Expand Up @@ -213,8 +215,9 @@ impl ReceiveStaticDescriptor {
}

pub fn new(buffer: *const u8, buffer_size: usize) -> Self {
let address_low = buffer as usize as u32;
let address_high = ((buffer as usize) >> 32) as u32;
let buffer = buffer.expose_provenance();
let address_low = buffer as u32;
let address_high = (buffer >> 32) as u32;

let mut bits: u32 = 0;
write_bits!(0, 15, bits, address_high);
Expand Down
4 changes: 3 additions & 1 deletion src/ipc/sf/vi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub trait ApplicationDisplay {
out_native_window: sf::OutMapAliasBuffer<'_, u8>,
) -> usize;
#[ipc_rid(2021)]
fn set_scaling_mode(&mut self, scaling_mode: ScalingMode, layer_id: LayerId);
fn destroy_managed_layer(&mut self, id: LayerId);
#[ipc_rid(2030)]
fn create_stray_layer(
&mut self,
Expand All @@ -119,6 +119,8 @@ pub trait ApplicationDisplay {
) -> (LayerId, usize);
#[ipc_rid(2031)]
fn destroy_stray_layer(&mut self, id: LayerId);
#[ipc_rid(2101)]
fn set_scaling_mode(&mut self, scaling_mode: ScalingMode, layer_id: LayerId);
#[ipc_rid(5202)]
fn get_display_vsync_event(&self, id: DisplayId) -> sf::CopyHandle;
}
Expand Down
Loading
Loading