From f2f59c75c07843d35df55453ec3e62d68927d0bf Mon Sep 17 00:00:00 2001 From: fincs Date: Wed, 29 Aug 2018 00:55:09 +0200 Subject: [PATCH] display/gfx.h & buffer_producer.h: Start major refactor, highly WIP --- nx/include/switch/display/buffer_producer.h | 42 ++--- nx/include/switch/display/gfx.h | 1 - nx/source/display/buffer_producer.c | 80 +++----- nx/source/display/gfx.c | 193 ++++++++------------ 4 files changed, 113 insertions(+), 203 deletions(-) diff --git a/nx/include/switch/display/buffer_producer.h b/nx/include/switch/display/buffer_producer.h index ffe95dd9..5feb5d70 100644 --- a/nx/include/switch/display/buffer_producer.h +++ b/nx/include/switch/display/buffer_producer.h @@ -1,36 +1,31 @@ #pragma once #include "types.h" -#include "../nvidia/ioctl.h" - -typedef struct { - u32 is_valid; - nvioctl_fence nv_fences[4]; -} PACKED BqFence; +#include "../nvidia/fence.h" typedef struct { s32 left; s32 top; s32 right; s32 bottom; -} PACKED BqRect; +} BqRect; typedef struct { - s64 timestamp; + struct { s64 timestamp; } PACKED; s32 isAutoTimestamp; BqRect crop; s32 scalingMode; u32 transform; // See the NATIVE_WINDOW_TRANSFORM_* enums. u32 stickyTransform; u32 unk[2]; - BqFence fence; -} PACKED BqQueueBufferInput; + NvMultiFence fence; +} BqQueueBufferInput; typedef struct { u32 width; u32 height; u32 transformHint; u32 numPendingBuffers; -} PACKED BqQueueBufferOutput; +} BqQueueBufferOutput; typedef struct { u32 magic; @@ -76,18 +71,15 @@ typedef struct { u32 unk_x68; u32 buffer_size1; u32 unk_x70[0x33]; // Normally all-zero. - u64 timestamp; - } PACKED data; -} PACKED BqGraphicBuffer; + struct { u64 timestamp; } PACKED; // unused + } data; +} BqGraphicBuffer; -Result bqInitialize(Binder *session); -void bqExit(void); - -Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf); -Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, BqFence *fence); -Result bqDetachBuffer(s32 slot); -Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output); -Result bqQuery(s32 what, s32* value); -Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output); -Result bqDisconnect(s32 api); -Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input); +Result bqRequestBuffer(Binder *b, s32 bufferIdx, BqGraphicBuffer *buf); +Result bqDequeueBuffer(Binder *b, bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, NvMultiFence *fence); +Result bqDetachBuffer(Binder *b, s32 slot); +Result bqQueueBuffer(Binder *b, s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output); +Result bqQuery(Binder *b, s32 what, s32* value); +Result bqConnect(Binder *b, s32 api, bool producerControlledByApp, BqQueueBufferOutput *output); +Result bqDisconnect(Binder *b, s32 api); +Result bqSetPreallocatedBuffer(Binder *b, s32 buf, BqGraphicBuffer *input); diff --git a/nx/include/switch/display/gfx.h b/nx/include/switch/display/gfx.h index 2fde1044..dc37947f 100644 --- a/nx/include/switch/display/gfx.h +++ b/nx/include/switch/display/gfx.h @@ -17,7 +17,6 @@ /// GfxMode set by \ref gfxSetMode. The default is GfxMode_LinearDouble. Note that the text-console (see console.h) sets this to GfxMode_TiledDouble. typedef enum { - GfxMode_TiledSingle, ///< Single-buffering with raw tiled (block-linear) framebuffer. GfxMode_TiledDouble, ///< Double-buffering with raw tiled (block-linear) framebuffer. GfxMode_LinearDouble ///< Double-buffering with linear framebuffer, which is transferred to the actual framebuffer by \ref gfxFlushBuffers(). } GfxMode; diff --git a/nx/source/display/buffer_producer.c b/nx/source/display/buffer_producer.c index d6b035ab..593de5db 100644 --- a/nx/source/display/buffer_producer.c +++ b/nx/source/display/buffer_producer.c @@ -9,7 +9,8 @@ // Hence names/params etc here are based on Android IGraphicBufferProducer.cpp. // Based on an old version of the enum from the above .cpp. -// Unknown whether all of these are correct for Switch. +// https://android.googlesource.com/platform/frameworks/native/+/29a3e90879fd96404c971e7187cd0e05927bbce0/libs/gui/IGraphicBufferProducer.cpp#35 + enum { /* 0x1 */ REQUEST_BUFFER = BINDER_FIRST_CALL_TRANSACTION, /* 0x2 */ SET_BUFFER_COUNT, @@ -24,39 +25,23 @@ enum { /* 0xB */ DISCONNECT, /* 0xC */ SET_SIDEBAND_STREAM, /* 0xD */ ALLOCATE_BUFFERS, - /* 0xE */ GRAPHIC_BUFFER_INIT, // Custom Switch-specific command - unofficial name. + /* 0xE */ SET_PREALLOCATED_BUFFER, // Custom Switch-specific command }; -static char g_bq_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer"; +static const char g_bq_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer"; -static Binder *g_bqBinderSession; - -Result bqInitialize(Binder *session) -{ - g_bqBinderSession = session; - return 0; -} - -void bqExit(void) -{ - g_bqBinderSession = NULL; -} - -Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf) +Result bqRequestBuffer(Binder *b, s32 bufferIdx, BqGraphicBuffer *buf) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, bufferIdx); - rc = parcelTransact(g_bqBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply); + rc = parcelTransact(b, REQUEST_BUFFER, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { int nonNull = parcelReadInt32(&parcel_reply); @@ -83,14 +68,11 @@ Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf) return rc; } -Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, BqFence *fence) +Result bqDequeueBuffer(Binder *b, bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, NvMultiFence *fence) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); @@ -102,7 +84,7 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, parcelWriteInt32(&parcel, format); parcelWriteUInt32(&parcel, usage); - rc = parcelTransact(g_bqBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply); + rc = parcelTransact(b, DEQUEUE_BUFFER, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { *buf = parcelReadInt32(&parcel_reply); @@ -112,11 +94,11 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, void* tmp_ptr; tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmp_size); - if (tmp_ptr == NULL || tmp_size != sizeof(BqFence)) + if (tmp_ptr == NULL || tmp_size != sizeof(NvMultiFence)) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (fence) - memcpy(fence, tmp_ptr, sizeof(BqFence)); + memcpy(fence, tmp_ptr, sizeof(NvMultiFence)); } int result = parcelReadInt32(&parcel_reply); @@ -127,21 +109,18 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, return rc; } -Result bqDetachBuffer(s32 slot) +Result bqDetachBuffer(Binder *b, s32 slot) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, slot); - rc = parcelTransact(g_bqBinderSession, DETACH_BUFFER, &parcel, &parcel_reply); + rc = parcelTransact(b, DETACH_BUFFER, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { //TODO: parse reply @@ -150,14 +129,11 @@ Result bqDetachBuffer(s32 slot) return rc; } -Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output) +Result bqQueueBuffer(Binder *b, s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); @@ -165,7 +141,7 @@ Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *ou parcelWriteInt32(&parcel, buf); parcelWriteFlattenedObject(&parcel, input, sizeof(*input)); - rc = parcelTransact(g_bqBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply); + rc = parcelTransact(b, QUEUE_BUFFER, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { if (parcelReadData(&parcel_reply, output, sizeof(*output)) == NULL) @@ -179,21 +155,18 @@ Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *ou return rc; } -Result bqQuery(s32 what, s32* value) +Result bqQuery(Binder *b, s32 what, s32* value) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, what); - rc = parcelTransact(g_bqBinderSession, QUERY, &parcel, &parcel_reply); + rc = parcelTransact(b, QUERY, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { *value = parcelReadInt32(&parcel_reply); @@ -206,14 +179,11 @@ Result bqQuery(s32 what, s32* value) return rc; } -Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output) +Result bqConnect(Binder *b, s32 api, bool producerControlledByApp, BqQueueBufferOutput *output) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); @@ -224,7 +194,7 @@ Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *out parcelWriteInt32(&parcel, api); parcelWriteInt32(&parcel, producerControlledByApp); - rc = parcelTransact(g_bqBinderSession, CONNECT, &parcel, &parcel_reply); + rc = parcelTransact(b, CONNECT, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { if (parcelReadData(&parcel_reply, output, sizeof(*output)) == NULL) @@ -238,21 +208,18 @@ Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *out return rc; } -Result bqDisconnect(s32 api) +Result bqDisconnect(Binder *b, s32 api) { Result rc; Parcel parcel, parcel_reply; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, api); - rc = parcelTransact(g_bqBinderSession, DISCONNECT, &parcel, &parcel_reply); + rc = parcelTransact(b, DISCONNECT, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { // TODO: parse reply @@ -261,15 +228,12 @@ Result bqDisconnect(s32 api) return rc; } -Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input) +Result bqSetPreallocatedBuffer(Binder *b, s32 buf, BqGraphicBuffer *input) { Result rc; Parcel parcel, parcel_reply; bool flag = 0; - if (g_bqBinderSession == NULL) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelCreate(&parcel); parcelCreate(&parcel_reply); @@ -283,7 +247,7 @@ Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input) if (flag) parcelWriteFlattenedObject(&parcel, input, sizeof(BqGraphicBuffer)); - rc = parcelTransact(g_bqBinderSession, GRAPHIC_BUFFER_INIT, &parcel, &parcel_reply); + rc = parcelTransact(b, SET_PREALLOCATED_BUFFER, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { int result = parcelReadInt32(&parcel_reply); diff --git a/nx/source/display/gfx.c b/nx/source/display/gfx.c index 58662c11..2df537ae 100644 --- a/nx/source/display/gfx.c +++ b/nx/source/display/gfx.c @@ -20,11 +20,10 @@ static Binder 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 u32 g_gfx_ProducerSlotsRequested = 0; static u8 *g_gfxFramebuf; static size_t g_gfxFramebufSize; static u32 g_gfxFramebufHandle; -static BqFence g_gfx_DequeueBuffer_fence; static BqQueueBufferOutput g_gfx_Connect_QueueBufferOutput; static BqQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput; @@ -51,7 +50,6 @@ static s32 g_gfx_autoresolution_docked_height; extern u32 __nx_applet_type; extern u32 g_nvgfx_totalframebufs; -extern nvioctl_fence g_nvgfx_nvhostgpu_gpfifo_fence; //static Result _gfxGetDisplayResolution(u64 *width, u64 *height); @@ -64,17 +62,7 @@ static BqQueueBufferInput g_gfxQueueBufferData = { .transform = NATIVE_WINDOW_TRANSFORM_FLIP_V, .stickyTransform = 0x0, .unk = {0x0, 0x1}, - - .fence = { - .is_valid = 0x1, - .nv_fences = { - { - .id = 0xffffffff, //Official sw sets this to the output fence from the last nvioctlChannel_SubmitGPFIFO(). - .value = 0x0, - }, - {0xffffffff, 0x0}, {0xffffffff, 0x0}, {0xffffffff, 0x0}, - }, - } + .fence = {0}, }; // Some of this struct is based on tegra_dc_ext_flip_windowattr. @@ -108,50 +96,56 @@ static BqGraphicBuffer g_gfx_BufferInitData = { } }; -static Result _gfxDequeueBuffer(void) { - Result rc=0; - BqFence *fence = &g_gfx_DequeueBuffer_fence; - BqFence tmp_fence; - bool async=0; +NvMultiFence debugfence; +Result debugfenceresult; - if (g_gfxMode == GfxMode_TiledSingle) { - g_gfxCurrentProducerBuffer = -1; +static Result _gfxDequeueBuffer(void) { + if (g_gfxCurrentProducerBuffer >= 0) return 0; + + 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; + + if (!(g_gfx_ProducerSlotsRequested & BIT(slot))) { + rc = bqRequestBuffer(&g_gfxBinderSession, slot, NULL); + if (R_FAILED(rc)) + return rc; // todo: cancelbuffer or something + g_gfx_ProducerSlotsRequested |= BIT(slot); } - memcpy(&tmp_fence, fence, sizeof(BqFence));//Offical sw waits on the fence from the previous DequeueBuffer call. Using the fence from the current DequeueBuffer call results in nvgfxEventWait() failing. + debugfence = fence; + for (u32 i = 0; i < fence.num_fences; i ++) { + if ((s32)fence.fences[i].id >= 0) { + // todo: figure out why fencewait sucks + /*rc =*/ debugfenceresult = nvgfxEventWait(fence.fences[i].id, fence.fences[i].value, 0); + //if (R_FAILED(rc)) + // break; + } + } - rc = bqDequeueBuffer(async, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &g_gfxCurrentProducerBuffer, fence); - - //Only run nvgfxEventWait when the fence is valid and the id is not NO_FENCE. - if (R_SUCCEEDED(rc) && tmp_fence.is_valid && tmp_fence.nv_fences[0].id!=0xffffffff) rc = nvgfxEventWait(tmp_fence.nv_fences[0].id, tmp_fence.nv_fences[0].value, -1); - - if (R_SUCCEEDED(rc)) g_gfxCurrentBuffer = (g_gfxCurrentBuffer + 1) & (g_nvgfx_totalframebufs-1); - - //if (R_SUCCEEDED(rc)) rc = nvgfxSubmitGpfifo(); + if (R_SUCCEEDED(rc)) { + g_gfxCurrentProducerBuffer = slot; + g_gfxCurrentBuffer = g_gfxCurrentProducerBuffer; + } return rc; } -static Result _gfxQueueBuffer(s32 buf) { +static Result _gfxQueueBuffer(void) { Result rc=0; - if (buf == -1) return 0; - - g_gfxQueueBufferData.timestamp = svcGetSystemTick();//This is probably not the proper value for the timestamp, but shouldn't(?) matter. - //if (g_nvgfx_nvhostgpu_gpfifo_fence.id) memcpy(&g_gfxQueueBufferData.fence.nv_fences[0], &g_nvgfx_nvhostgpu_gpfifo_fence, sizeof(nvioctl_fence)); - //if (g_nvgfx_nvhostgpu_gpfifo_fence.id) rc = nvgfxEventWait(g_nvgfx_nvhostgpu_gpfifo_fence.id, g_nvgfx_nvhostgpu_gpfifo_fence.value, -1); - if (R_FAILED(rc)) return rc; - - rc = bqQueueBuffer(buf, &g_gfxQueueBufferData, &g_gfx_QueueBuffer_QueueBufferOutput); - if (R_FAILED(rc)) return rc; + if (g_gfxCurrentProducerBuffer >= 0) { + rc = bqQueueBuffer(&g_gfxBinderSession, g_gfxCurrentProducerBuffer, &g_gfxQueueBufferData, &g_gfx_QueueBuffer_QueueBufferOutput); + g_gfxCurrentProducerBuffer = -1; + } return rc; } Result gfxInitDefault(void) { Result rc=0; - u32 i=0; if(g_gfxInitialized)return 0; @@ -167,8 +161,8 @@ Result gfxInitDefault(void) { g_gfx_drawflip = true; g_gfxQueueBufferData.transform = NATIVE_WINDOW_TRANSFORM_FLIP_V; - memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); - memset(&g_gfx_DequeueBuffer_fence, 0, sizeof(g_gfx_DequeueBuffer_fence)); + //memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); + g_gfx_ProducerSlotsRequested = 0; if (g_gfx_framebuf_width==0 || g_gfx_framebuf_height==0) { g_gfx_framebuf_width = 1280; @@ -214,68 +208,39 @@ Result gfxInitDefault(void) { if (R_SUCCEEDED(rc)) rc = viCreateLayer(&g_gfxDisplay, &g_gfxLayer); - if (R_SUCCEEDED(rc)) rc = viSetLayerScalingMode(&g_gfxLayer, ViScalingMode_Default); - if (R_SUCCEEDED(rc)) { binderCreate(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxLayer.igbp_binder_obj_id); rc = binderInitSession(&g_gfxBinderSession, 0x0f); } + 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); + + if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = true; + if (R_SUCCEEDED(rc)) rc = nvInitialize(); - if (R_SUCCEEDED(rc)) rc = bqInitialize(&g_gfxBinderSession); - - if (R_SUCCEEDED(rc)) rc = bqConnect(NATIVE_WINDOW_API_CPU, 0, &g_gfx_Connect_QueueBufferOutput); - - if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = 1; - if (R_SUCCEEDED(rc)) rc = nvgfxInitialize(); if (R_SUCCEEDED(rc)) rc = nvgfxGetFramebuffer(&g_gfxFramebuf, &g_gfxFramebufSize, &g_gfxFramebufHandle); - if (R_SUCCEEDED(rc)) { //Official sw would use bqRequestBuffer() when required during swap-buffers/or similar, but that's not really an option here due to gfxSetDoubleBuffering(). - for(i=0; i<2; i++) { - rc = _gfxDequeueBuffer(); - if (R_FAILED(rc)) break; - - rc = bqRequestBuffer(g_gfxCurrentProducerBuffer, NULL); - 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)) { - g_gfxCurrentProducerBuffer = -1; - break; - } - } - } - if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(); - if (R_SUCCEEDED(rc)) { - if (__nx_applet_type == AppletType_Application) { //It's unknown whether there's a better way to handle this. - svcSleepThread(2000000000); - } - else { - for(i=0; i<2; i++) gfxWaitForVsync(); - } - } + // todo: figure out if it's possible to wait for the 'Nintendo' logo screen to finish displaying (NSO, applet type: Application) if (R_FAILED(rc)) { - _gfxQueueBuffer(g_gfxCurrentProducerBuffer); - for(i=0; i<2; i++) { - if (g_gfx_ProducerSlotsRequested[i]) bqDetachBuffer(i); + if (g_gfx_ProducerConnected) { + _gfxQueueBuffer(); + for(u32 i=0; i<32; i++) { + if (g_gfx_ProducerSlotsRequested & BIT(i)) bqDetachBuffer(&g_gfxBinderSession, i); + } + bqDisconnect(&g_gfxBinderSession, NATIVE_WINDOW_API_CPU); + nvgfxExit(); + nvExit(); } - if (g_gfx_ProducerConnected) bqDisconnect(NATIVE_WINDOW_API_CPU); - nvgfxExit(); - bqExit(); binderClose(&g_gfxBinderSession); - nvExit(); - viCloseLayer(&g_gfxLayer); viCloseDisplay(&g_gfxDisplay); viExit(); @@ -298,7 +263,7 @@ Result gfxInitDefault(void) { g_gfx_framebuf_width = 0; g_gfx_framebuf_height = 0; - memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); + g_gfx_ProducerSlotsRequested = 0; } if (R_SUCCEEDED(rc)) g_gfxInitialized = 1; @@ -308,34 +273,29 @@ Result 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]) bqDetachBuffer(i); + if (g_gfx_ProducerConnected) { + _gfxQueueBuffer(); + for(u32 i=0; i<32; i++) { + if (g_gfx_ProducerSlotsRequested & BIT(i)) bqDetachBuffer(&g_gfxBinderSession, i); + } + bqDisconnect(&g_gfxBinderSession, NATIVE_WINDOW_API_CPU); + nvgfxExit(); + nvExit(); } - if (g_gfx_ProducerConnected) bqDisconnect(2); - nvgfxExit(); - - bqExit(); binderClose(&g_gfxBinderSession); - - nvExit(); - viCloseLayer(&g_gfxLayer); + viCloseDisplay(&g_gfxDisplay); + viExit(); if(g_gfxDisplayVsyncEvent != INVALID_HANDLE) { svcCloseHandle(g_gfxDisplayVsyncEvent); g_gfxDisplayVsyncEvent = INVALID_HANDLE; } - viCloseDisplay(&g_gfxDisplay); - - viExit(); - free(g_gfxFramebufLinear); g_gfxFramebufLinear = NULL; @@ -352,8 +312,7 @@ void gfxExit(void) gfxConfigureAutoResolution(0, 0, 0, 0, 0); - memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested)); - + g_gfx_ProducerSlotsRequested = 0; memset(&g_gfxQueueBufferData.crop, 0, sizeof(g_gfxQueueBufferData.crop)); } @@ -442,33 +401,29 @@ Result _gfxGraphicBufferInit(s32 buf, u32 nvmap_id, u32 nvmap_handle) { g_gfx_BufferInitData.data.buffer_offset = g_gfx_singleframebuf_size*buf; g_gfx_BufferInitData.data.timestamp = svcGetSystemTick(); - return bqGraphicBufferInit(buf, &g_gfx_BufferInitData); + return bqSetPreallocatedBuffer(&g_gfxBinderSession, buf, &g_gfx_BufferInitData); } -static void _waitevent(Handle *handle) { - Result rc=0, rc2=0; - - svcResetSignal(*handle); +static void _waitevent(Handle handle) { + Result rc; do { - rc = svcWaitSynchronizationSingle(*handle, U64_MAX); + rc = svcWaitSynchronizationSingle(handle, U64_MAX); + svcResetSignal(handle); + } while ((rc & 0x3FFFFF) == 0xFA01); - if (R_SUCCEEDED(rc)) - rc2 = svcResetSignal(*handle); - - } while(R_FAILED(rc) || (rc2 & 0x3FFFFF)==0xFA01); - - if (R_FAILED(rc2)) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadGfxEventWait)); + if (R_FAILED(rc)) + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadGfxEventWait)); } void gfxWaitForVsync(void) { - _waitevent(&g_gfxDisplayVsyncEvent); + _waitevent(g_gfxDisplayVsyncEvent); } void gfxSwapBuffers(void) { Result rc=0; - rc = _gfxQueueBuffer(g_gfxCurrentProducerBuffer); + rc = _gfxQueueBuffer(); if (R_FAILED(rc)) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadGfxQueueBuffer));