diff --git a/nx/include/switch/gfx/buffer_producer.h b/nx/include/switch/gfx/buffer_producer.h index 7c54a9e2..87016b39 100644 --- a/nx/include/switch/gfx/buffer_producer.h +++ b/nx/include/switch/gfx/buffer_producer.h @@ -3,9 +3,8 @@ #include typedef struct { - u32 unk_x0; - nvioctl_fence nv_fence; - u32 unk_xc[0x18>>2]; + u32 is_valid; + nvioctl_fence nv_fences[4]; } PACKED bufferProducerFence; typedef struct { diff --git a/nx/include/switch/gfx/nvgfx.h b/nx/include/switch/gfx/nvgfx.h index 4b17b123..8f1101b0 100644 --- a/nx/include/switch/gfx/nvgfx.h +++ b/nx/include/switch/gfx/nvgfx.h @@ -1,4 +1,4 @@ Result nvgfxInitialize(void); void nvgfxExit(void); -Result nvgfxEventInit(void); +Result nvgfxEventWait(u32 syncpt_id, u32 threshold); Result nvgfxGetFramebuffer(u8 **buffer, size_t *size); diff --git a/nx/include/switch/services/binder.h b/nx/include/switch/services/binder.h index 169fda10..3b246274 100644 --- a/nx/include/switch/services/binder.h +++ b/nx/include/switch/services/binder.h @@ -1,6 +1,8 @@ #define BINDER_FIRST_CALL_TRANSACTION 0x1 typedef struct { + bool created; + bool initialized; Handle sessionHandle; s32 id; Handle nativeHandle; diff --git a/nx/source/gfx/binder.c b/nx/source/gfx/binder.c index fdb4b47f..64adbe85 100644 --- a/nx/source/gfx/binder.c +++ b/nx/source/gfx/binder.c @@ -4,6 +4,7 @@ void binderCreateSession(binderSession *session, Handle sessionHandle, s32 id) { memset(session, 0, sizeof(binderSession)); + session->created = 1; session->sessionHandle = sessionHandle; session->id = id; session->nativeHandle = INVALID_HANDLE; @@ -14,6 +15,9 @@ Result binderInitSession(binderSession *session, u32 unk0) { Result rc = 0; + if (!session->created) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + if (session->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_ALREADYINITIALIZED); + rc = binderAdjustRefcount(session, 1, 0); if (R_FAILED(rc)) @@ -41,6 +45,8 @@ Result binderInitSession(binderSession *session, u32 unk0) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); } + session->initialized = 1; + rc = ipcQueryPointerBufferSize(session->sessionHandle, &session->ipcBufferSize); if (R_FAILED(rc)) { @@ -57,13 +63,23 @@ Result binderInitSession(binderSession *session, u32 unk0) void binderExitSession(binderSession *session) { - binderAdjustRefcount(session, -1, 1); - binderAdjustRefcount(session, -1, 0); + if (!session->created) return; - if (session->nativeHandle != INVALID_HANDLE) { - svcCloseHandle(session->nativeHandle); - session->nativeHandle = INVALID_HANDLE; + if (session->initialized) { + binderAdjustRefcount(session, -1, 1); + binderAdjustRefcount(session, -1, 0); + + if (session->nativeHandle != INVALID_HANDLE) { + svcCloseHandle(session->nativeHandle); + session->nativeHandle = INVALID_HANDLE; + } } + + session->sessionHandle = INVALID_HANDLE; + session->id = 0; + + session->created = 0; + session->initialized = 0; } static Result _binderTransactParcel( @@ -72,6 +88,8 @@ static Result _binderTransactParcel( void* parcel_reply, size_t parcel_reply_size, u32 flags) { + if (!session->created || !session->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + IpcCommand c; ipcInitialize(&c); @@ -116,6 +134,8 @@ static Result _binderTransactParcelAuto( void* parcel_reply, size_t parcel_reply_size, u32 flags) { + if (!session->created || !session->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + IpcCommand c; ipcInitialize(&c); @@ -193,6 +213,8 @@ Result binderTransactParcel( Result binderAdjustRefcount(binderSession *session, s32 addval, s32 type) { + if (!session->created) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + IpcCommand c; ipcInitialize(&c); @@ -230,6 +252,8 @@ Result binderAdjustRefcount(binderSession *session, s32 addval, s32 type) Result binderGetNativeHandle(binderSession *session, u32 inval, Handle *handle_out) { + if (!session->created) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); + IpcCommand c; ipcInitialize(&c); diff --git a/nx/source/gfx/buffer_producer.c b/nx/source/gfx/buffer_producer.c index 3d4417c0..12d37c34 100644 --- a/nx/source/gfx/buffer_producer.c +++ b/nx/source/gfx/buffer_producer.c @@ -103,8 +103,8 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format void* tmp_ptr; tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize); - if (tmp_ptr==NULL || tmpsize!=0x24) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); - if (fence) memcpy(fence, tmp_ptr, 0x24); + if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerFence)) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); + if (fence) memcpy(fence, tmp_ptr, sizeof(bufferProducerFence)); } int result = parcelReadInt32(&parcel_reply); diff --git a/nx/source/gfx/gfx.c b/nx/source/gfx/gfx.c index 373233f1..d3c7bc22 100644 --- a/nx/source/gfx/gfx.c +++ b/nx/source/gfx/gfx.c @@ -24,6 +24,7 @@ extern u32 __nx_applet_type; extern u32 g_nvgfx_totalframebufs; extern size_t g_nvgfx_singleframebuf_size; +//TODO: Let the user configure some of this? static bufferProducerQueueBufferInput g_gfxQueueBufferData = { .timestamp = 0x0, .isAutoTimestamp = 0x1, @@ -31,27 +32,26 @@ static bufferProducerQueueBufferInput g_gfxQueueBufferData = { .scalingMode = 0x0, .transform = 0x2, .stickyTransform = 0x0, - /*.unk = {0x0, 0x1}, + .unk = {0x0, 0x1}, .fence = { - .unk_x0 = 0x1, - .nv_fence = { - .id = 0x42, - .value = 0x13f4, + .is_valid = 0x1, + .nv_fences = { + { + .id = /*0x42*/0xffffffff, + .value = /*0x13f4*/0x0, + }, + {0xffffffff, 0x0}, {0xffffffff, 0x0}, {0xffffffff, 0x0}, }, - .unk_xc = { - 0xffffffff, 0x0, 0xffffffff, 0x0, 0xffffffff, 0x0 - }, - }*/ + } }; static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) { u32 *bufptr = (u32*)buf; //Validate ParcelData{Size|Offset}. - if((u64)bufptr[1] >= size || (u64)bufptr[0] >= size || ((u64)bufptr[1])+((u64)bufptr[0]) >= size) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); + if((u64)bufptr[1] > size || (u64)bufptr[0] > size || ((u64)bufptr[1])+((u64)bufptr[0]) > size) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); if(bufptr[0] < 0xc) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); - //bufptr = start of ParcelData bufptr = (u32*)&buf[bufptr[1]]; @@ -70,6 +70,8 @@ static Result _gfxDequeueBuffer(bufferProducerFence *fence) { rc = bufferProducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer, fence); + //if (R_SUCCEEDED(rc) && fence) rc = nvgfxEventWait(fence->nv_fences[0].id, fence->nv_fences[0].value); + if (R_SUCCEEDED(rc)) g_gfxCurrentBuffer = (g_gfxCurrentBuffer + 1) & (g_nvgfx_totalframebufs-1); return rc; @@ -161,11 +163,9 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L } } - if (R_SUCCEEDED(rc)) rc = nvgfxEventInit(); - if (R_SUCCEEDED(rc)) svcSleepThread(3000000000); - if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(NULL); + if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence); /*if (R_SUCCEEDED(rc)) { //Workaround a gfx display issue. for(i=0; i<2; i++)gfxWaitForVsync(); @@ -292,6 +292,11 @@ void gfxSwapBuffers() { if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence); + #ifdef BUFFERSWAP_DELAY_HACK + gfxWaitForVsync(); + gfxWaitForVsync(); + #endif + if (R_FAILED(rc)) fatalSimple(rc); } diff --git a/nx/source/gfx/nvgfx.c b/nx/source/gfx/nvgfx.c index fcc71a29..e2b12ae9 100644 --- a/nx/source/gfx/nvgfx.c +++ b/nx/source/gfx/nvgfx.c @@ -442,14 +442,14 @@ void nvgfxExit(void) { g_nvgfxInitialized = 0; } -Result nvgfxEventInit(void) { +Result nvgfxEventWait(u32 syncpt_id, u32 threshold) { Result rc=0; - /*if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc)) { do { - rc = nvioctlNvhostCtrl_EventWait(g_nvgfx_fd_nvhostctrl, 0x42, 0x1ca7, 0x64, 0, &g_nvgfx_nvhostctrl_eventres); + rc = nvioctlNvhostCtrl_EventWait(g_nvgfx_fd_nvhostctrl, /*0x42, 0x1ca7*/syncpt_id, threshold, 0x64, 0, &g_nvgfx_nvhostctrl_eventres); } while(rc==5);//timeout error - }*/ + } //Currently broken. //if (R_SUCCEEDED(rc)) rc = nvQueryEvent(g_nvgfx_fd_nvhostctrl, g_nvgfx_nvhostctrl_eventres, &g_nvgfx_nvhostctrl_eventhandle);