From 41cd7bb7252e927a06a085a39dbd8fa3308665c5 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 21 Nov 2017 13:19:35 -0500 Subject: [PATCH] Exit gfx properly. Adjusted the name for _gfxproducer_InterfaceDescriptor. --- nx/include/switch/gfx/gfxproducer.h | 2 ++ nx/source/gfx/gfx.c | 45 +++++++++++++++++++---- nx/source/gfx/gfxproducer.c | 55 +++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/nx/include/switch/gfx/gfxproducer.h b/nx/include/switch/gfx/gfxproducer.h index 16c89c1b..71064235 100644 --- a/nx/include/switch/gfx/gfxproducer.h +++ b/nx/include/switch/gfx/gfxproducer.h @@ -3,7 +3,9 @@ void gfxproducerExit(); Result gfxproducerRequestBuffer(s32 bufferIdx); Result gfxproducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf); +Result gfxproducerDetachBuffer(s32 slot); Result gfxproducerQueueBuffer(s32 buf, u8 input[0x5c]); Result gfxproducerQuery(s32 what, s32* value); Result gfxproducerConnect(s32 api, bool producerControlledByApp); +Result gfxproducerDisconnect(s32 api); Result gfxproducerTegraBufferInit(s32 buf, u8 input[0x178]); diff --git a/nx/source/gfx/gfx.c b/nx/source/gfx/gfx.c index f11e9fed..85a9ac30 100644 --- a/nx/source/gfx/gfx.c +++ b/nx/source/gfx/gfx.c @@ -11,6 +11,8 @@ static s32 g_gfxNativeWindow_ID; static binderSession g_gfxBinderSession; static s32 g_gfxCurrentBuffer = 0; static s32 g_gfxCurrentProducerBuffer = 0; +static bool g_gfx_ProducerConnected = 0; +static bool g_gfx_ProducerSlotsRequested[2] = {0, 0}; static u8 *g_gfxFramebuf; static size_t g_gfxFramebufSize; @@ -91,11 +93,14 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L g_gfxNativeWindow_ID = 0; g_gfxDisplayVsyncEvent = INVALID_HANDLE; g_gfxCurrentBuffer = -1; - g_gfxCurrentProducerBuffer = 0; + g_gfxCurrentProducerBuffer = -1; + g_gfx_ProducerConnected = 0; g_gfxFramebuf = NULL; g_gfxFramebufSize = 0; g_gfxDoubleBuf = 1; + memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); + rc = viInitialize(servicetype); if (R_FAILED(rc)) return rc; @@ -120,6 +125,8 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L if (R_SUCCEEDED(rc)) rc = gfxproducerConnect(2, 0); + if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = 1; + if (R_SUCCEEDED(rc)) rc = nvgfxInitialize(); if (R_SUCCEEDED(rc)) rc = nvgfxGetFramebuffer(&g_gfxFramebuf, &g_gfxFramebufSize); @@ -132,10 +139,15 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L rc = gfxproducerRequestBuffer(g_gfxCurrentProducerBuffer); if (R_FAILED(rc)) break; + g_gfx_ProducerSlotsRequested[i] = 1; + //Officially, nvioctlNvmap_FromID() and nvioctlChannel_SubmitGPFIFO() are used here. rc = _gfxQueueBuffer(g_gfxCurrentProducerBuffer); - if (R_FAILED(rc)) break; + if (R_FAILED(rc)) { + g_gfxCurrentProducerBuffer = -1; + break; + } } } @@ -148,10 +160,17 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L } if (R_FAILED(rc)) { + _gfxQueueBuffer(g_gfxCurrentProducerBuffer); + for(i=0; i<2; i++) { + if (g_gfx_ProducerSlotsRequested[i]) gfxproducerDetachBuffer(i); + } + if (g_gfx_ProducerConnected) gfxproducerDisconnect(2); + nvgfxExit(); gfxproducerExit(); - nvExit(); binderExitSession(&g_gfxBinderSession); + nvExit(); + viCloseLayer(&g_gfxLayer); viCloseDisplay(&g_gfxDisplay); viExit(); @@ -163,9 +182,12 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L g_gfxNativeWindow_ID = 0; g_gfxCurrentBuffer = 0; - g_gfxCurrentProducerBuffer = 0; + g_gfxCurrentProducerBuffer = -1; + g_gfx_ProducerConnected = 0; g_gfxFramebuf = NULL; g_gfxFramebufSize = 0; + + memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); } if (R_SUCCEEDED(rc)) g_gfxInitialized = 1; @@ -196,16 +218,22 @@ void gfxInitDefault(void) { } void gfxExit(void) { + u32 i=0; if(!g_gfxInitialized)return; + _gfxQueueBuffer(g_gfxCurrentProducerBuffer); + for(i=0; i<2; i++) { + if (g_gfx_ProducerSlotsRequested[i]) gfxproducerDetachBuffer(i); + } + if (g_gfx_ProducerConnected) gfxproducerDisconnect(2); + nvgfxExit(); gfxproducerExit(); + binderExitSession(&g_gfxBinderSession); nvExit(); - binderExitSession(&g_gfxBinderSession); - viCloseLayer(&g_gfxLayer); if(g_gfxDisplayVsyncEvent != INVALID_HANDLE) { @@ -221,9 +249,12 @@ void gfxExit(void) { g_gfxNativeWindow_ID = 0; g_gfxCurrentBuffer = 0; - g_gfxCurrentProducerBuffer = 0; + g_gfxCurrentProducerBuffer = -1; + g_gfx_ProducerConnected = 0; g_gfxFramebuf = NULL; g_gfxFramebufSize = 0; + + memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); } void gfxWaitForVsync() { diff --git a/nx/source/gfx/gfxproducer.c b/nx/source/gfx/gfxproducer.c index 9546098c..e9d6ad60 100644 --- a/nx/source/gfx/gfxproducer.c +++ b/nx/source/gfx/gfxproducer.c @@ -22,7 +22,7 @@ enum { TEGRA_BUFFER_INIT, //0xE (Custom Switch-specific command - unofficial name) }; -static char _gfxproducer_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer"; +static char g_gfxproducer_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer"; static binderSession *g_gfxproducerBinderSession; @@ -45,7 +45,7 @@ Result gfxproducerRequestBuffer(s32 bufferIdx) { parcelInitializeContext(&parcel); parcelInitializeContext(&parcel_reply); - parcelWriteInterfaceToken(&parcel, _gfxproducer_InterfaceDescriptor); + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); parcelWriteInt32(&parcel, bufferIdx); rc = parcelTransact(g_gfxproducerBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply); @@ -65,7 +65,7 @@ Result gfxproducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u parcelInitializeContext(&parcel); parcelInitializeContext(&parcel_reply); - parcelWriteInterfaceToken(&parcel, _gfxproducer_InterfaceDescriptor); + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); parcelWriteInt32(&parcel, async); parcelWriteUInt32(&parcel, width); @@ -83,6 +83,26 @@ Result gfxproducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u return 0; } +Result gfxproducerDetachBuffer(s32 slot) { + Result rc; + parcelContext parcel, parcel_reply; + + if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + + parcelInitializeContext(&parcel); + parcelInitializeContext(&parcel_reply); + + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); + parcelWriteInt32(&parcel, slot); + + rc = parcelTransact(g_gfxproducerBinderSession, DETACH_BUFFER, &parcel, &parcel_reply); + if (R_FAILED(rc)) return rc; + + //TODO: parse reply + + return 0; +} + Result gfxproducerQueueBuffer(s32 buf, u8 input[0x5c]) { Result rc; parcelContext parcel, parcel_reply; @@ -92,7 +112,7 @@ Result gfxproducerQueueBuffer(s32 buf, u8 input[0x5c]) { parcelInitializeContext(&parcel); parcelInitializeContext(&parcel_reply); - parcelWriteInterfaceToken(&parcel, _gfxproducer_InterfaceDescriptor); + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); parcelWriteInt32(&parcel, buf); parcelWriteData(&parcel, input, 0x5c); @@ -114,7 +134,7 @@ Result gfxproducerQuery(s32 what, s32* value) { parcelInitializeContext(&parcel); parcelInitializeContext(&parcel_reply); - parcelWriteInterfaceToken(&parcel, _gfxproducer_InterfaceDescriptor); + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); parcelWriteInt32(&parcel, what); @@ -137,7 +157,7 @@ Result gfxproducerConnect(s32 api, bool producerControlledByApp) { parcelInitializeContext(&parcel); parcelInitializeContext(&parcel_reply); - parcelWriteInterfaceToken(&parcel, _gfxproducer_InterfaceDescriptor); + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); //Hard-code this as if listener==NULL, since that's not known to be used officially. parcelWriteInt32(&parcel, 0); @@ -153,6 +173,27 @@ Result gfxproducerConnect(s32 api, bool producerControlledByApp) { return 0; } +Result gfxproducerDisconnect(s32 api) { + Result rc; + parcelContext parcel, parcel_reply; + + if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + + parcelInitializeContext(&parcel); + parcelInitializeContext(&parcel_reply); + + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); + + parcelWriteInt32(&parcel, api); + + rc = parcelTransact(g_gfxproducerBinderSession, DISCONNECT, &parcel, &parcel_reply); + if (R_FAILED(rc)) return rc; + + //TODO: parse reply + + return 0; +} + Result gfxproducerTegraBufferInit(s32 buf, u8 input[0x178]) { Result rc; parcelContext parcel, parcel_reply; @@ -162,7 +203,7 @@ Result gfxproducerTegraBufferInit(s32 buf, u8 input[0x178]) { parcelInitializeContext(&parcel); parcelInitializeContext(&parcel_reply); - parcelWriteInterfaceToken(&parcel, _gfxproducer_InterfaceDescriptor); + parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor); parcelWriteInt32(&parcel, buf); parcelWriteData(&parcel, input, 0x178);