diff --git a/nx/include/switch/display/buffer_producer.h b/nx/include/switch/display/buffer_producer.h index 5feb5d70..0fa48747 100644 --- a/nx/include/switch/display/buffer_producer.h +++ b/nx/include/switch/display/buffer_producer.h @@ -79,6 +79,7 @@ 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 bqCancelBuffer(Binder *b, s32 buf, NvMultiFence *fence); Result bqQuery(Binder *b, s32 what, s32* value); Result bqConnect(Binder *b, s32 api, bool producerControlledByApp, BqQueueBufferOutput *output); Result bqDisconnect(Binder *b, s32 api); diff --git a/nx/source/display/buffer_producer.c b/nx/source/display/buffer_producer.c index 3b304345..2eec4558 100644 --- a/nx/source/display/buffer_producer.c +++ b/nx/source/display/buffer_producer.c @@ -147,6 +147,24 @@ Result bqQueueBuffer(Binder *b, s32 buf, BqQueueBufferInput *input, BqQueueBuffe return rc; } +Result bqCancelBuffer(Binder *b, s32 buf, NvMultiFence *fence) +{ + Result rc; + Parcel parcel, parcel_reply; + + parcelCreate(&parcel); + parcelCreate(&parcel_reply); + + parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); + parcelWriteInt32(&parcel, buf); + parcelWriteFlattenedObject(&parcel, fence, sizeof(*fence)); + + rc = parcelTransact(b, CANCEL_BUFFER, &parcel, &parcel_reply); + // Reply parcel has no content + + return rc; +} + Result bqQuery(Binder *b, s32 what, s32* value) { Result rc; diff --git a/nx/source/display/gfx.c b/nx/source/display/gfx.c index e37ae842..7a6f0464 100644 --- a/nx/source/display/gfx.c +++ b/nx/source/display/gfx.c @@ -119,8 +119,10 @@ static Result _gfxDequeueBuffer(void) { if (!(g_gfx_ProducerSlotsRequested & BIT(slot))) { rc = bqRequestBuffer(&g_gfxBinderSession, slot, NULL); - if (R_FAILED(rc)) - return rc; // todo: cancelbuffer or something + if (R_FAILED(rc)) { + bqCancelBuffer(&g_gfxBinderSession, slot, &fence); + return rc; + } g_gfx_ProducerSlotsRequested |= BIT(slot); } @@ -147,6 +149,17 @@ static Result _gfxQueueBuffer(void) { return rc; } +static Result _gfxCancelBuffer(void) { + Result rc=0; + + if (g_gfxCurrentProducerBuffer >= 0) { + rc = bqCancelBuffer(&g_gfxBinderSession, g_gfxCurrentProducerBuffer, &g_gfxQueueBufferData.fence); + g_gfxCurrentProducerBuffer = -1; + } + + return rc; +} + Result gfxInitDefault(void) { Result rc=0; @@ -237,7 +250,7 @@ Result gfxInitDefault(void) { if (R_FAILED(rc)) { if (g_gfx_ProducerConnected) { - _gfxQueueBuffer(); + _gfxCancelBuffer(); for(u32 i=0; i<32; i++) { if (g_gfx_ProducerSlotsRequested & BIT(i)) bqDetachBuffer(&g_gfxBinderSession, i); } @@ -281,7 +294,7 @@ void gfxExit(void) return; if (g_gfx_ProducerConnected) { - _gfxQueueBuffer(); + _gfxCancelBuffer(); for(u32 i=0; i<32; i++) { if (g_gfx_ProducerSlotsRequested & BIT(i)) bqDetachBuffer(&g_gfxBinderSession, i); }