From dd4a9bbca6e1cf40e40cde4f4fc0bc265d3cbf34 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 19 Dec 2017 12:13:37 -0500 Subject: [PATCH] Added bufferProducerGraphicBuffer struct. Parse the bufferProducerRequestBuffer parcel reply properly. Renamed bufferProducerTegraBufferInit to bufferProducerGraphicBufferInit + renamed the enum for it, and handle input/output for it properly. Properly return rc in bufferProducerGraphicBufferInit(). --- nx/include/switch/gfx/buffer_producer.h | 8 +++++-- nx/source/gfx/buffer_producer.c | 30 ++++++++++++++++--------- nx/source/gfx/gfx.c | 2 +- nx/source/gfx/nvgfx.c | 20 +++++++++-------- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/nx/include/switch/gfx/buffer_producer.h b/nx/include/switch/gfx/buffer_producer.h index 619dc0e1..35d90d32 100644 --- a/nx/include/switch/gfx/buffer_producer.h +++ b/nx/include/switch/gfx/buffer_producer.h @@ -25,6 +25,10 @@ typedef struct { u32 numPendingBuffers; } PACKED bufferProducerQueueBufferOutput; +typedef struct { + u32 unk[0x16c>>2]; +} PACKED bufferProducerGraphicBuffer; + //From Android window.h. /* attributes queriable with query() */ enum { @@ -49,11 +53,11 @@ enum { Result bufferProducerInitialize(binderSession *session); void bufferProducerExit(); -Result bufferProducerRequestBuffer(s32 bufferIdx); +Result bufferProducerRequestBuffer(s32 bufferIdx, bufferProducerGraphicBuffer *buf); Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, bufferProducerFence *fence); Result bufferProducerDetachBuffer(s32 slot); Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input, bufferProducerQueueBufferOutput *output); Result bufferProducerQuery(s32 what, s32* value); Result bufferProducerConnect(s32 api, bool producerControlledByApp, bufferProducerQueueBufferOutput *output); Result bufferProducerDisconnect(s32 api); -Result bufferProducerTegraBufferInit(s32 buf, u8 input[0x178]); +Result bufferProducerGraphicBufferInit(s32 buf, bufferProducerGraphicBuffer *input); diff --git a/nx/source/gfx/buffer_producer.c b/nx/source/gfx/buffer_producer.c index c45a15f5..663510e7 100644 --- a/nx/source/gfx/buffer_producer.c +++ b/nx/source/gfx/buffer_producer.c @@ -20,7 +20,7 @@ enum { /* 0xB */ DISCONNECT, /* 0xC */ SET_SIDEBAND_STREAM, /* 0xD */ ALLOCATE_BUFFERS, - /* 0xE */ TEGRA_BUFFER_INIT, // Custom Switch-specific command - unofficial name. + /* 0xE */ GRAPHIC_BUFFER_INIT, // Custom Switch-specific command - unofficial name. }; static char g_bufferProducer_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer"; @@ -38,7 +38,7 @@ void bufferProducerExit() g_bufferProducerBinderSession = NULL; } -Result bufferProducerRequestBuffer(s32 bufferIdx) +Result bufferProducerRequestBuffer(s32 bufferIdx, bufferProducerGraphicBuffer *buf) { Result rc; Parcel parcel, parcel_reply; @@ -55,12 +55,15 @@ Result bufferProducerRequestBuffer(s32 bufferIdx) rc = parcelTransact(g_bufferProducerBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { - /* int nonNull = parcelReadInt32(&parcel_reply); if (nonNull != 0) { - // Fixme - fatalSimple(222 | (100 << 9)); + size_t tmpsize=0; + void* tmp_ptr; + + tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize); + if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerGraphicBuffer)) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); + if (buf) memcpy(buf, tmp_ptr, sizeof(bufferProducerGraphicBuffer)); } int status = parcelReadInt32(&parcel_reply); @@ -68,7 +71,6 @@ Result bufferProducerRequestBuffer(s32 bufferIdx) if (status != 0) { rc = MAKERESULT(MODULE_LIBNX, LIBNX_BUFFERPRODUCER_ERROR); } - */ } return rc; @@ -247,10 +249,11 @@ Result bufferProducerDisconnect(s32 api) return rc; } -Result bufferProducerTegraBufferInit(s32 buf, u8 input[0x178]) +Result bufferProducerGraphicBufferInit(s32 buf, bufferProducerGraphicBuffer *input) { Result rc; Parcel parcel, parcel_reply; + bool flag = 0; if (g_bufferProducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED); @@ -259,14 +262,19 @@ Result bufferProducerTegraBufferInit(s32 buf, u8 input[0x178]) parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInt32(&parcel, buf); - parcelWriteData(&parcel, input, 0x178); - rc = parcelTransact(g_bufferProducerBinderSession, TEGRA_BUFFER_INIT, &parcel, &parcel_reply); + if (input!=NULL) flag = 1; + parcelWriteInt32(&parcel, flag); + if (flag) parcelWriteFlattenedObject(&parcel, input, sizeof(bufferProducerGraphicBuffer)); + + rc = parcelTransact(g_bufferProducerBinderSession, GRAPHIC_BUFFER_INIT, &parcel, &parcel_reply); if (R_SUCCEEDED(rc)) { - // TODO: parse reply + int result = parcelReadInt32(&parcel_reply); + if (result != 0) + rc = MAKERESULT(MODULE_LIBNX, LIBNX_BUFFERPRODUCER_ERROR); } - return 0; + return rc; } diff --git a/nx/source/gfx/gfx.c b/nx/source/gfx/gfx.c index 2745c2ca..555592f2 100644 --- a/nx/source/gfx/gfx.c +++ b/nx/source/gfx/gfx.c @@ -162,7 +162,7 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L rc = _gfxDequeueBuffer(); if (R_FAILED(rc)) break; - rc = bufferProducerRequestBuffer(g_gfxCurrentProducerBuffer); + rc = bufferProducerRequestBuffer(g_gfxCurrentProducerBuffer, NULL); if (R_FAILED(rc)) break; g_gfx_ProducerSlotsRequested[i] = 1; diff --git a/nx/source/gfx/nvgfx.c b/nx/source/gfx/nvgfx.c index 41339343..7f8ec8b1 100644 --- a/nx/source/gfx/nvgfx.c +++ b/nx/source/gfx/nvgfx.c @@ -47,8 +47,9 @@ static u64 nvmap_obj6_mapbuffer_xdb_offset; static u64 g_nvgfx_gpfifo_pos = 0; //Some of this struct is based on tegra_dc_ext_flip_windowattr. -static u32 g_gfxprod_BufferInitData[0x178>>2] = { -0x1, 0x16c, 0x0, +//TODO: How much of this struct do official apps really set? Most of it seems to be used as-is from the bufferProducerRequestBuffer() output. +static bufferProducerGraphicBuffer g_gfxprod_BufferInitData = { +.unk = { 0x47424652, 1280, 720, 1280, @@ -79,6 +80,7 @@ static u32 g_gfxprod_BufferInitData[0x178>>2] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 //Unknown, some timestamp perhaps? +} }; Result nvmapobjInitialize(nvmapobj *obj, size_t size) { @@ -132,7 +134,7 @@ Result nvgfxInitialize(void) { u32 pos=0, i=0; s32 tmp=0; u32 tmpval=0; - u64 *ptr64 = (u64*)g_gfxprod_BufferInitData; + u64 *ptr64 = (u64*)g_gfxprod_BufferInitData.unk; if(g_nvgfxInitialized)return 0; u32 framebuf_nvmap_handle = 0;//Special handle ID for framebuf/windowbuf. @@ -311,12 +313,12 @@ Result nvgfxInitialize(void) { //The above gets a nvmap_handle, but normally it's the same value passed to nvioctlNvmap_GetId(). - g_gfxprod_BufferInitData[0xa] = i; - g_gfxprod_BufferInitData[0xe] = tmpval; - g_gfxprod_BufferInitData[0x20] = tmpval; - g_gfxprod_BufferInitData[0x21] = g_nvgfx_singleframebuf_size*i; - ptr64[0x170>>3] = svcGetSystemTick(); - rc = bufferProducerTegraBufferInit(i, (u8*)g_gfxprod_BufferInitData); + g_gfxprod_BufferInitData.unk[0x7] = i; + g_gfxprod_BufferInitData.unk[0xb] = tmpval; + g_gfxprod_BufferInitData.unk[0x1d] = tmpval; + g_gfxprod_BufferInitData.unk[0x1e] = g_nvgfx_singleframebuf_size*i; + ptr64[0x164>>3] = svcGetSystemTick(); + rc = bufferProducerGraphicBufferInit(i, &g_gfxprod_BufferInitData); if (R_FAILED(rc)) break; } if (R_FAILED(rc)) break;