From b5abd52b8b4ebc85e2cde7528ec60b8e2e65e246 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 5 Nov 2017 00:50:58 -0400 Subject: [PATCH] Implemented viSetLayerScalingMode(). Implemented vsync handling. Minor other change. --- nx/include/switch/gfx/gfx.h | 1 + nx/include/switch/services/vi.h | 10 +++++ nx/source/gfx/gfx.c | 18 ++++++++ nx/source/services/vi.c | 76 +++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) diff --git a/nx/include/switch/gfx/gfx.h b/nx/include/switch/gfx/gfx.h index 9e81e2e0..74dca81a 100644 --- a/nx/include/switch/gfx/gfx.h +++ b/nx/include/switch/gfx/gfx.h @@ -1,3 +1,4 @@ /// Do not use viInitialize/viExit when using these. void gfxInitDefault(void); void gfxExit(void); +void gfxWaitForVsync(); diff --git a/nx/include/switch/services/vi.h b/nx/include/switch/services/vi.h index 4465fc7e..ea7448c9 100644 --- a/nx/include/switch/services/vi.h +++ b/nx/include/switch/services/vi.h @@ -22,6 +22,11 @@ typedef enum { VILAYERFLAGS_Default = 0x1, } viLayerFlags; +/// Used with viSetLayerScalingMode. +typedef enum { + VISCALINGMODE_Default = 0x2, +} viScalingMode; + Result viInitialize(viServiceType servicetype); void viExit(void); Handle viGetSessionService(void); @@ -35,3 +40,8 @@ Result viOpenDisplay(const char *DisplayName, viDisplay *display); Result viCloseDisplay(viDisplay *display); Result viOpenLayer(u8 NativeWindow[0x100], u64 *NativeWindow_Size, const viDisplay *display, viLayer *layer, u32 LayerFlags, u64 LayerId); Result viCloseLayer(viLayer *layer); + +/// See viScalingMode. +Result viSetLayerScalingMode(viLayer *layer, u32 ScalingMode); + +Result viGetDisplayVsyncEvent(viDisplay *display, Handle *handle_out); diff --git a/nx/source/gfx/gfx.c b/nx/source/gfx/gfx.c index 29b77d6e..fff01c79 100644 --- a/nx/source/gfx/gfx.c +++ b/nx/source/gfx/gfx.c @@ -3,6 +3,7 @@ static bool g_gfxInitialized = 0; static viDisplay g_gfxDisplay; +static Handle g_gfxDisplayVsyncEvent = INVALID_HANDLE; static viLayer g_gfxLayer; static u8 g_gfxNativeWindow[0x100]; static u64 g_gfxNativeWindow_Size; @@ -30,14 +31,19 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L if(g_gfxInitialized)return 0; g_gfxNativeWindow_ID = 0; + g_gfxDisplayVsyncEvent = INVALID_HANDLE; rc = viInitialize(servicetype); if (R_FAILED(rc)) return rc; rc = viOpenDisplay(DisplayName, &g_gfxDisplay); + if (R_SUCCEEDED(rc)) rc = viGetDisplayVsyncEvent(&g_gfxDisplay, &g_gfxDisplayVsyncEvent); + if (R_SUCCEEDED(rc)) rc = viOpenLayer(g_gfxNativeWindow, &g_gfxNativeWindow_Size, &g_gfxDisplay, &g_gfxLayer, LayerFlags, LayerId); + if (R_SUCCEEDED(rc)) rc = viSetLayerScalingMode(&g_gfxLayer, VISCALINGMODE_Default); + if (R_SUCCEEDED(rc)) rc = _gfxGetNativeWindowID(g_gfxNativeWindow, g_gfxNativeWindow_Size, &g_gfxNativeWindow_ID); if (R_SUCCEEDED(rc)) { @@ -70,6 +76,12 @@ void gfxExit(void) { binderExitSession(&g_gfxBinderSession); viCloseLayer(&g_gfxLayer); + + if(g_gfxDisplayVsyncEvent != INVALID_HANDLE) { + svcCloseHandle(g_gfxDisplayVsyncEvent); + g_gfxDisplayVsyncEvent = INVALID_HANDLE; + } + viCloseDisplay(&g_gfxDisplay); viExit(); @@ -78,3 +90,9 @@ void gfxExit(void) { g_gfxNativeWindow_ID = 0; } +void gfxWaitForVsync() { + s32 tmpindex=0; + svcClearEvent(g_gfxDisplayVsyncEvent); + svcWaitSynchronization(&tmpindex, &g_gfxDisplayVsyncEvent, 1, U64_MAX); +} + diff --git a/nx/source/services/vi.c b/nx/source/services/vi.c index 475d7dd1..391f8374 100644 --- a/nx/source/services/vi.c +++ b/nx/source/services/vi.c @@ -305,6 +305,7 @@ static Result _viCreateStrayLayer(u8 NativeWindow[0x100], u64 *NativeWindow_Size raw->magic = SFCI_MAGIC; raw->cmd_id = 2030; raw->LayerFlags = LayerFlags; + raw->pad = 0; raw->DisplayId = display->DisplayId; Result rc = ipcDispatch(g_viIApplicationDisplayService); @@ -394,3 +395,78 @@ Result viCloseLayer(viLayer *layer) { return rc; } +Result viSetLayerScalingMode(viLayer *layer, u32 ScalingMode) { + IpcCommand c; + ipcInitialize(&c); + + if (!layer->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + + struct { + u64 magic; + u64 cmd_id; + u32 ScalingMode; + u32 pad; + u64 LayerId; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 2101; + raw->ScalingMode = ScalingMode; + raw->pad = 0; + raw->LayerId = layer->LayerId; + + Result rc = ipcDispatch(g_viIApplicationDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcCommandResponse r; + ipcParseResponse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result viGetDisplayVsyncEvent(viDisplay *display, Handle *handle_out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 DisplayId; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 5202; + raw->DisplayId = display->DisplayId; + + Result rc = ipcDispatch(g_viIApplicationDisplayService); + + if (R_SUCCEEDED(rc)) { + IpcCommandResponse r; + ipcParseResponse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *handle_out = r.Handles[0]; + } + } + + return rc; +} +