From 798d8ff50cee63e1b52a05303a97e3c6ba0fb9df Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 12 Nov 2018 22:32:22 -0800 Subject: [PATCH] Add vi wrappers for system StrayLayer usage. --- nx/include/switch/services/vi.h | 19 ++ nx/source/services/vi.c | 410 +++++++++++++++++++++++++++++++- 2 files changed, 426 insertions(+), 3 deletions(-) diff --git a/nx/include/switch/services/vi.h b/nx/include/switch/services/vi.h index c376dcd6..d2d7be30 100644 --- a/nx/include/switch/services/vi.h +++ b/nx/include/switch/services/vi.h @@ -39,6 +39,13 @@ typedef enum { ViScalingMode_Default = 0x2, } ViScalingMode; +/// Used with viSetDisplayPowerState. +typedef enum { + ViPowerState_Off = 0, + ViPowerState_NotScanning = 1, + ViPowerState_On = 2, +} ViPowerState; + Result viInitialize(ViServiceType service_type); void viExit(void); @@ -48,6 +55,9 @@ Service* viGetSession_ISystemDisplayService(void); Service* viGetSession_IManagerDisplayService(void); Service* viGetSession_IHOSBinderDriverIndirect(void); +// Misc functions +Result viSetContentVisibility(bool v); + // Display functions Result viOpenDisplay(const char *display_name, ViDisplay *display); @@ -59,12 +69,21 @@ static inline Result viOpenDefaultDisplay(ViDisplay *display) } Result viGetDisplayResolution(ViDisplay *display, u64 *width, u64 *height); +Result viGetDisplayLogicalResolution(ViDisplay *display, u32 *width, u32 *height); +Result viSetDisplayMagnification(ViDisplay *display, u32 x, u32 y, u32 width, u32 height); Result viGetDisplayVsyncEvent(ViDisplay *display, Event *event_out); +Result viSetDisplayPowerState(ViDisplay *display, ViPowerState state); +Result viSetDisplayAlpha(ViDisplay *display, float alpha); +Result viGetDisplayMinimumZ(ViDisplay *display, u64 *z); +Result viGetDisplayMaximumZ(ViDisplay *display, u64 *z); // Layer functions Result viCreateLayer(const ViDisplay *display, ViLayer *layer); Result viCreateManagedLayer(const ViDisplay *display, ViLayerFlags layer_flags, u64 aruid, u64 *layer_id); +Result viSetLayerSize(ViLayer *layer, u64 width, u64 height); +Result viSetLayerZ(ViLayer *layer, u64 z); +Result viSetLayerPosition(ViLayer *layer, float x, float y); Result viCloseLayer(ViLayer *layer); Result viSetLayerScalingMode(ViLayer *layer, ViScalingMode scaling_mode); diff --git a/nx/source/services/vi.c b/nx/source/services/vi.c index 8ddb7c33..2d9b1bf2 100644 --- a/nx/source/services/vi.c +++ b/nx/source/services/vi.c @@ -276,6 +276,95 @@ Result viGetDisplayResolution(ViDisplay *display, u64 *width, u64 *height) return rc; } +Result viGetDisplayLogicalResolution(ViDisplay *display, u32 *width, u32 *height) +{ + IpcCommand c; + ipcInitialize(&c); + + if (!display->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u64 display_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1203; + raw->display_id = display->display_id; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u32 width; + u32 height; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (width) *width = resp->width; + if (height) *height = resp->height; + } + } + + return rc; +} + +Result viSetDisplayMagnification(ViDisplay *display, u32 x, u32 y, u32 width, u32 height) +{ + IpcCommand c; + ipcInitialize(&c); + + if (!display->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u32 x; + u32 y; + u32 width; + u32 height; + u64 display_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1204; + raw->display_id = display->display_id; + raw->x = x; + raw->y = y; + raw->width = width; + raw->height = height; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result viGetDisplayVsyncEvent(ViDisplay *display, Event *event_out) { IpcCommand c; @@ -317,6 +406,166 @@ Result viGetDisplayVsyncEvent(ViDisplay *display, Event *event_out) return rc; } +Result viSetDisplayPowerState(ViDisplay *display, ViPowerState state) +{ + IpcCommand c; + ipcInitialize(&c); + + if (!display->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u32 power_state; + u64 display_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 4205; + raw->display_id = display->display_id; + raw->power_state = state; + + Result rc = serviceIpcDispatch(&g_viIManagerDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result viSetDisplayAlpha(ViDisplay *display, float alpha) +{ + IpcCommand c; + ipcInitialize(&c); + + if (!display->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + float alpha; + u64 display_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 4201; + raw->display_id = display->display_id; + raw->alpha = alpha; + + Result rc = serviceIpcDispatch(&g_viIManagerDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result viGetDisplayMinimumZ(ViDisplay *display, u64 *z) { + IpcCommand c; + ipcInitialize(&c); + + if (!display->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u64 display_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1200; + raw->display_id = display->display_id; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u64 z; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (z) *z = resp->z; + } + } + + return rc; +} + +Result viGetDisplayMaximumZ(ViDisplay *display, u64 *z) { + IpcCommand c; + ipcInitialize(&c); + + if (!display->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u64 display_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1202; + raw->display_id = display->display_id; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u64 z; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + if (z) *z = resp->z; + } + } + + return rc; +} + Result viCreateManagedLayer(const ViDisplay *display, ViLayerFlags layer_flags, u64 aruid, u64 *layer_id) { IpcCommand c; @@ -364,6 +613,38 @@ Result viCreateManagedLayer(const ViDisplay *display, ViLayerFlags layer_flags, return rc; } +Result viSetContentVisibility(bool v) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 visibility; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 7000; + raw->visibility = v; + + Result rc = serviceIpcDispatch(&g_viIManagerDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + static Result _viOpenLayer(const ViDisplay *display, u64 layer_id, u64 aruid, u8 native_window[0x100], u64 *native_window_size) { IpcCommand c; @@ -428,12 +709,17 @@ static Result _viCreateStrayLayer(const ViDisplay *display, u32 layer_flags, u64 raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; - raw->cmd_id = 2030; + raw->cmd_id = g_viServiceType < ViServiceType_System ? 2030 : 2312; raw->layer_flags = layer_flags; raw->pad = 0; raw->display_id = display->display_id; - - Result rc = serviceIpcDispatch(&g_viIApplicationDisplayService); + + Result rc; + if (g_viServiceType < ViServiceType_System) { + rc = serviceIpcDispatch(&g_viIApplicationDisplayService); + } else { + rc = serviceIpcDispatch(&g_viISystemDisplayService); + } if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -508,6 +794,124 @@ _bad_parcel: return MAKERESULT(Module_Libnx, LibnxError_BadInput); } +Result viSetLayerSize(ViLayer *layer, u64 width, u64 height) { + IpcCommand c; + ipcInitialize(&c); + + if (!layer->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u64 layer_id; + u64 width; + u64 height; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2203; + raw->layer_id = layer->layer_id; + raw->width = width; + raw->height = height; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result viSetLayerZ(ViLayer *layer, u64 z) { + IpcCommand c; + ipcInitialize(&c); + + if (!layer->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + u64 layer_id; + u64 z; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2205; + raw->layer_id = layer->layer_id; + raw->z = z; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result viSetLayerPosition(ViLayer *layer, float x, float y) { + IpcCommand c; + ipcInitialize(&c); + + if (!layer->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + struct { + u64 magic; + u64 cmd_id; + float x; + float y; + u64 layer_id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2201; + raw->layer_id = layer->layer_id; + raw->x = x; + raw->y = y; + + Result rc = serviceIpcDispatch(&g_viISystemDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result viCloseLayer(ViLayer *layer) { IpcCommand c;