From 819a6f0d890dbf452eef15b3c9d1b4b0735d0d7c Mon Sep 17 00:00:00 2001 From: fincs Date: Fri, 31 Aug 2018 12:59:10 +0200 Subject: [PATCH] display/binder.h: refactoring and other changes: - Removed session_handle/native_handle state - Consequence of the above: simplified binderCreate/binderInitSession - Now using viGetSession_IHOSBinderDriverRelay internally - Changed binderGetNativeHandle to return an Event - Added readable aliases for binderAdjustRefcount - gfx: now using async bqDequeueBuffer when the binder event is available --- nx/include/switch/display/binder.h | 34 +++++++++++++---- nx/source/display/binder.c | 61 ++++++++++-------------------- nx/source/display/gfx.c | 24 ++++++++++-- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/nx/include/switch/display/binder.h b/nx/include/switch/display/binder.h index c54eff61..a8ad8689 100644 --- a/nx/include/switch/display/binder.h +++ b/nx/include/switch/display/binder.h @@ -1,23 +1,22 @@ #pragma once #include "../types.h" +#include "../kernel/event.h" #define BINDER_FIRST_CALL_TRANSACTION 0x1 typedef struct { - bool created; - bool initialized; - Handle session_handle; + bool created : 1; + bool initialized : 1; + bool has_transact_auto : 1; s32 id; - Handle native_handle; size_t ipc_buffer_size; - bool has_transact_auto; } Binder; // Note: binderClose will not close the session_handle provided to binderCreate. -void binderCreate(Binder* b, Handle session_handle, s32 id); +void binderCreate(Binder* b, s32 id); void binderClose(Binder* b); -Result binderInitSession(Binder* b, u32 unk0); +Result binderInitSession(Binder* b); Result binderTransactParcel( Binder* b, u32 code, @@ -26,5 +25,24 @@ Result binderTransactParcel( u32 flags); Result binderAdjustRefcount(Binder* b, s32 addval, s32 type); -Result binderGetNativeHandle(Binder* b, u32 unk0, Handle *handle_out); +Result binderGetNativeHandle(Binder* b, u32 unk0, Event *event_out); +static inline Result binderIncreaseWeakRef(Binder* b) +{ + return binderAdjustRefcount(b, 1, 0); +} + +static inline Result binderDecreaseWeakRef(Binder* b) +{ + return binderAdjustRefcount(b, -1, 0); +} + +static inline Result binderIncreaseStrongRef(Binder* b) +{ + return binderAdjustRefcount(b, 1, 1); +} + +static inline Result binderDecreaseStrongRef(Binder* b) +{ + return binderAdjustRefcount(b, -1, 1); +} diff --git a/nx/source/display/binder.c b/nx/source/display/binder.c index 678c423e..c72ba95b 100644 --- a/nx/source/display/binder.c +++ b/nx/source/display/binder.c @@ -3,19 +3,22 @@ #include "result.h" #include "kernel/ipc.h" #include "kernel/detect.h" +#include "services/vi.h" #include "display/binder.h" -void binderCreate(Binder* b, Handle session_handle, s32 id) +static Result _binderIpcDispatch(void) +{ + return serviceIpcDispatch(viGetSession_IHOSBinderDriverRelay()); +} + +void binderCreate(Binder* b, s32 id) { memset(b, 0, sizeof(Binder)); b->created = true; - b->session_handle = session_handle; b->id = id; - b->native_handle = INVALID_HANDLE; - b->has_transact_auto = false; } -Result binderInitSession(Binder* b, u32 unk0) +Result binderInitSession(Binder* b) { Result rc = 0; @@ -25,37 +28,19 @@ Result binderInitSession(Binder* b, u32 unk0) if (b->initialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); - rc = binderAdjustRefcount(b, 1, 0); - + rc = binderIncreaseWeakRef(b); if (R_FAILED(rc)) return rc; - rc = binderAdjustRefcount(b, 1, 1); - + rc = binderIncreaseStrongRef(b); if (R_FAILED(rc)) { - binderAdjustRefcount(b, -1, 0); + binderDecreaseStrongRef(b); return rc; } - rc = binderGetNativeHandle(b, unk0, &b->native_handle); - - if (R_FAILED(rc)) { - binderAdjustRefcount(b, -1, 1); - binderAdjustRefcount(b, -1, 0); - return rc; - } - - // When the output native_handle is 0 the Binder ID is probably invalid. - if (b->native_handle == 0) { - binderAdjustRefcount(b, -1, 1); - binderAdjustRefcount(b, -1, 0); - return MAKERESULT(Module_Libnx, LibnxError_BadInput); - } - b->initialized = true; - rc = ipcQueryPointerBufferSize(b->session_handle, &b->ipc_buffer_size); - + rc = ipcQueryPointerBufferSize(viGetSession_IHOSBinderDriverRelay()->handle, &b->ipc_buffer_size); if (R_FAILED(rc)) { binderClose(b); return rc; @@ -74,16 +59,10 @@ void binderClose(Binder* b) return; if (b->initialized) { - binderAdjustRefcount(b, -1, 1); - binderAdjustRefcount(b, -1, 0); - - if (b->native_handle != INVALID_HANDLE) { - svcCloseHandle(b->native_handle); - b->native_handle = INVALID_HANDLE; - } + binderDecreaseStrongRef(b); + binderDecreaseWeakRef(b); } - b->session_handle = INVALID_HANDLE; b->id = 0; b->created = false; @@ -120,7 +99,7 @@ static Result _binderTransactParcel( raw->code = code; raw->flags = flags; - Result rc = ipcDispatch(b->session_handle); + Result rc = _binderIpcDispatch(); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -167,7 +146,7 @@ static Result _binderTransactParcelAuto( raw->code = code; raw->flags = flags; - Result rc = ipcDispatch(b->session_handle); + Result rc = _binderIpcDispatch(); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -223,7 +202,7 @@ Result binderAdjustRefcount(Binder* b, s32 addval, s32 type) raw->addval = addval; raw->type = type; - Result rc = ipcDispatch(b->session_handle); + Result rc = _binderIpcDispatch(); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -240,7 +219,7 @@ Result binderAdjustRefcount(Binder* b, s32 addval, s32 type) return rc; } -Result binderGetNativeHandle(Binder* b, u32 inval, Handle *handle_out) +Result binderGetNativeHandle(Binder* b, u32 inval, Event *event_out) { if (!b->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); @@ -262,7 +241,7 @@ Result binderGetNativeHandle(Binder* b, u32 inval, Handle *handle_out) raw->session_id = b->id; raw->inval = inval; - Result rc = ipcDispatch(b->session_handle); + Result rc = _binderIpcDispatch(); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -276,7 +255,7 @@ Result binderGetNativeHandle(Binder* b, u32 inval, Handle *handle_out) rc = resp->result; if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; + eventLoadRemote(event_out, r.Handles[0], false); } } diff --git a/nx/source/display/gfx.c b/nx/source/display/gfx.c index c15f73e4..3786dd0e 100644 --- a/nx/source/display/gfx.c +++ b/nx/source/display/gfx.c @@ -17,6 +17,7 @@ static ViDisplay g_gfxDisplay; static Event g_gfxDisplayVsyncEvent; static ViLayer g_gfxLayer; static Binder g_gfxBinderSession; +static Event g_gfxBinderEvent; static s32 g_gfxCurrentBuffer = 0; static s32 g_gfxCurrentProducerBuffer = 0; static bool g_gfx_ProducerConnected = 0; @@ -102,8 +103,19 @@ static Result _gfxDequeueBuffer(void) { NvMultiFence fence; s32 slot; - Result rc = bqDequeueBuffer(&g_gfxBinderSession, false, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &slot, &fence); - if (R_FAILED(rc)) return rc; + Result rc; + + if (g_gfxBinderEvent.revent != INVALID_HANDLE) { + do { + eventWait(&g_gfxBinderEvent, U64_MAX); + rc = bqDequeueBuffer(&g_gfxBinderSession, true, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &slot, &fence); + } while (rc == MAKERESULT(Module_Libnx, LibnxError_BufferProducerError)); // todo: check for error -11 + } + else + rc = bqDequeueBuffer(&g_gfxBinderSession, false, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &slot, &fence); + + if (R_FAILED(rc)) + return rc; if (!(g_gfx_ProducerSlotsRequested & BIT(slot))) { rc = bqRequestBuffer(&g_gfxBinderSession, slot, NULL); @@ -199,10 +211,12 @@ Result gfxInitDefault(void) { if (R_SUCCEEDED(rc)) rc = viCreateLayer(&g_gfxDisplay, &g_gfxLayer); if (R_SUCCEEDED(rc)) { - binderCreate(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxLayer.igbp_binder_obj_id); - rc = binderInitSession(&g_gfxBinderSession, 0x0f); + binderCreate(&g_gfxBinderSession, g_gfxLayer.igbp_binder_obj_id); + rc = binderInitSession(&g_gfxBinderSession); } + if (R_SUCCEEDED(rc)) binderGetNativeHandle(&g_gfxBinderSession, 0x0f, &g_gfxBinderEvent); // a failure here is not fatal + if (R_SUCCEEDED(rc)) rc = viSetLayerScalingMode(&g_gfxLayer, ViScalingMode_Default); if (R_SUCCEEDED(rc)) rc = bqConnect(&g_gfxBinderSession, NATIVE_WINDOW_API_CPU, 0, &g_gfx_Connect_QueueBufferOutput); @@ -233,6 +247,7 @@ Result gfxInitDefault(void) { nvExit(); } + eventClose(&g_gfxBinderEvent); binderClose(&g_gfxBinderSession); viCloseLayer(&g_gfxLayer); eventClose(&g_gfxDisplayVsyncEvent); @@ -276,6 +291,7 @@ void gfxExit(void) nvExit(); } + eventClose(&g_gfxBinderEvent); binderClose(&g_gfxBinderSession); viCloseLayer(&g_gfxLayer); eventClose(&g_gfxDisplayVsyncEvent);