NWindow: Internal rework to fix resource leak in nwindowReleaseBuffers

This commit is contained in:
fincs 2018-12-12 21:14:54 +01:00
parent 5e8a88ce85
commit 4eef02bd71
2 changed files with 59 additions and 21 deletions

View File

@ -34,6 +34,7 @@ typedef struct NWindow {
u32 default_height; u32 default_height;
u32 swap_interval; u32 swap_interval;
bool is_connected; bool is_connected;
bool producer_controlled_by_app;
bool consumer_running_behind; bool consumer_running_behind;
} NWindow; } NWindow;
@ -183,6 +184,6 @@ Result nwindowCancelBuffer(NWindow* nw, s32 slot, const NvMultiFence* fence);
Result nwindowQueueBuffer(NWindow* nw, s32 slot, const NvMultiFence* fence); Result nwindowQueueBuffer(NWindow* nw, s32 slot, const NvMultiFence* fence);
/// Releases all buffers registered with a \ref NWindow. /// Releases all buffers registered with a \ref NWindow.
void nwindowReleaseBuffers(NWindow* nw); Result nwindowReleaseBuffers(NWindow* nw);
///@} ///@}

View File

@ -16,6 +16,33 @@ static void _nwindowUpdate(NWindow* nw, const BqBufferOutput* out)
nw->consumer_running_behind = out->numPendingBuffers > 1; nw->consumer_running_behind = out->numPendingBuffers > 1;
} }
static Result _nwindowConnect(NWindow* nw)
{
BqBufferOutput bqoutput;
Result rc = bqConnect(&nw->bq, NATIVE_WINDOW_API_CPU, nw->producer_controlled_by_app, &bqoutput);
if (R_SUCCEEDED(rc)) {
nw->is_connected = true;
_nwindowUpdate(nw, &bqoutput);
}
return rc;
}
static Result _nwindowDisconnect(NWindow* nw)
{
Result rc = bqDisconnect(&nw->bq, NATIVE_WINDOW_API_CPU);
if (R_SUCCEEDED(rc)) {
nw->is_connected = false;
nw->slots_configured = 0;
nw->slots_requested = 0;
nw->cur_slot = -1;
nw->width = 0;
nw->height = 0;
nw->format = 0;
nw->usage = 0;
}
return rc;
}
bool nwindowIsValid(NWindow* nw) bool nwindowIsValid(NWindow* nw)
{ {
return nw && nw->magic == NWINDOW_MAGIC; return nw && nw->magic == NWINDOW_MAGIC;
@ -30,6 +57,7 @@ Result nwindowCreate(NWindow* nw, s32 binder_id, bool producer_controlled_by_app
nw->swap_interval = 1; nw->swap_interval = 1;
nw->cur_slot = -1; nw->cur_slot = -1;
nw->format = ~0U; nw->format = ~0U;
nw->producer_controlled_by_app = producer_controlled_by_app;
binderCreate(&nw->bq, binder_id); binderCreate(&nw->bq, binder_id);
rc = binderInitSession(&nw->bq); rc = binderInitSession(&nw->bq);
@ -37,14 +65,8 @@ Result nwindowCreate(NWindow* nw, s32 binder_id, bool producer_controlled_by_app
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
binderGetNativeHandle(&nw->bq, 0x0f, &nw->event); binderGetNativeHandle(&nw->bq, 0x0f, &nw->event);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc))
BqBufferOutput bqoutput; rc = _nwindowConnect(nw);
rc = bqConnect(&nw->bq, NATIVE_WINDOW_API_CPU, producer_controlled_by_app, &bqoutput);
if (R_SUCCEEDED(rc)) {
nw->is_connected = true;
_nwindowUpdate(nw, &bqoutput);
}
}
if (R_FAILED(rc)) if (R_FAILED(rc))
nwindowClose(nw); nwindowClose(nw);
@ -62,10 +84,8 @@ void nwindowClose(NWindow* nw)
if (!nwindowIsValid(nw)) if (!nwindowIsValid(nw))
return; return;
if (nw->is_connected) { if (nw->is_connected)
nwindowReleaseBuffers(nw); _nwindowDisconnect(nw);
bqDisconnect(&nw->bq, NATIVE_WINDOW_API_CPU);
}
eventClose(&nw->event); eventClose(&nw->event);
binderClose(&nw->bq); binderClose(&nw->bq);
@ -148,6 +168,14 @@ Result nwindowConfigureBuffer(NWindow* nw, s32 slot, NvGraphicBuffer* buf)
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
} }
if (!nw->is_connected) {
Result rc = _nwindowConnect(nw);
if (R_FAILED(rc)) {
mutexUnlock(&nw->mutex);
return rc;
}
}
if (!nw->width) if (!nw->width)
nw->width = buf->planes[0].width; nw->width = buf->planes[0].width;
if (!nw->height) if (!nw->height)
@ -183,7 +211,7 @@ Result nwindowDequeueBuffer(NWindow* nw, s32* out_slot, NvMultiFence* out_fence)
mutexLock(&nw->mutex); mutexLock(&nw->mutex);
if (nw->cur_slot >= 0) { if (!nw->slots_configured || nw->cur_slot >= 0) {
mutexUnlock(&nw->mutex); mutexUnlock(&nw->mutex);
return MAKERESULT(Module_Libnx, LibnxError_BadGfxDequeueBuffer); return MAKERESULT(Module_Libnx, LibnxError_BadGfxDequeueBuffer);
} }
@ -286,15 +314,24 @@ Result nwindowQueueBuffer(NWindow* nw, s32 slot, const NvMultiFence* fence)
return rc; return rc;
} }
void nwindowReleaseBuffers(NWindow* nw) Result nwindowReleaseBuffers(NWindow* nw)
{ {
if (!nwindowIsValid(nw)) if (!nwindowIsValid(nw))
return; return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
for (u32 i = 0; i < 64; i ++) Result rc = 0;
if (nw->slots_configured & (1UL << i)) mutexLock(&nw->mutex);
bqDetachBuffer(&nw->bq, i);
nw->slots_configured = 0; if (nw->cur_slot >= 0)
nw->slots_requested = 0; rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
else if (nw->is_connected && nw->slots_configured) {
for (u32 i = 0; i < 64; i ++)
if (nw->slots_configured & (1UL << i))
bqDetachBuffer(&nw->bq, i);
rc = _nwindowDisconnect(nw);
}
mutexUnlock(&nw->mutex);
return rc;
} }