From b5773670114fed5e4a5ab28cca2238db68cb29e1 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Fri, 17 Nov 2017 01:16:17 -0500 Subject: [PATCH] Implemented nvioctlNvmap_FromID() and nvioctlNvmap_GetID(). Added PARCEL_LOGGING define in parcel.c. Fixed the 'code' value used in gfxproducerQueueBuffer(). Moved some gfxproducer init into nvgfx. Moved some nvgfx event init into nvgfxEventInit(). Updated the code using gfxproducerBufferInit() for setting the nvmap-handles. Disabled a nvQueryEvent() call which now fails. Other changes. The setup framebuf/windowbuf is now displayed. --- nx/include/switch/gfx/nvgfx.h | 1 + nx/include/switch/gfx/nvioctl.h | 2 + nx/source/gfx/gfx.c | 57 +++--------------- nx/source/gfx/gfxproducer.c | 2 +- nx/source/gfx/nvgfx.c | 100 +++++++++++++++++++++++++++----- nx/source/gfx/nvioctl.c | 38 ++++++++++++ nx/source/gfx/parcel.c | 14 +++-- 7 files changed, 146 insertions(+), 68 deletions(-) diff --git a/nx/include/switch/gfx/nvgfx.h b/nx/include/switch/gfx/nvgfx.h index f70b0549..aa0a0873 100644 --- a/nx/include/switch/gfx/nvgfx.h +++ b/nx/include/switch/gfx/nvgfx.h @@ -1,2 +1,3 @@ Result nvgfxInitialize(void); void nvgfxExit(void); +Result nvgfxEventInit(void); diff --git a/nx/include/switch/gfx/nvioctl.h b/nx/include/switch/gfx/nvioctl.h index c36e4725..2ff3d385 100644 --- a/nx/include/switch/gfx/nvioctl.h +++ b/nx/include/switch/gfx/nvioctl.h @@ -92,7 +92,9 @@ Result nvioctlNvhostAsGpu_GetVARegions(u32 fd, nvioctl_va_region regions[2]); Result nvioctlNvhostAsGpu_InitializeEx(u32 fd, u32 big_page_size); Result nvioctlNvmap_Create(u32 fd, u32 size, u32 *nvmap_handle); +Result nvioctlNvmap_FromID(u32 fd, u32 id, u32 *nvmap_handle); Result nvioctlNvmap_Alloc(u32 fd, u32 nvmap_handle, u32 heapmask, u32 flags, u32 align, u8 kind, void* addr); +Result nvioctlNvmap_GetID(u32 fd, u32 nvmap_handle, u32 *id); Result nvioctlChannel_SetNvmapFd(u32 fd, u32 nvmap_fd); Result nvioctlChannel_SubmitGPFIFO(u32 fd, nvioctl_gpfifo_entry *entries, u32 num_entries, u32 flags, nvioctl_fence *fence_out); diff --git a/nx/source/gfx/gfx.c b/nx/source/gfx/gfx.c index b4a2dcfd..5765eac2 100644 --- a/nx/source/gfx/gfx.c +++ b/nx/source/gfx/gfx.c @@ -24,38 +24,6 @@ static u32 g_gfxQueueBufferData[0x5c>>2] = { 0xffffffff, 0x0, 0xffffffff, 0x0, 0xffffffff, 0x0}; -static u32 g_gfxBufferInitData[0x178>>2] = { -0x1, 0x16c, 0x0, -0x47424652, -1280, 720, -1280, -0x1, 0xb00, 0x2a, 0x0, -0x0, 0x51, 0xffffffff, 0xcb8, -0x0, 0xdaffcaff, 0x2a, 0x0, -0xb00, 0x1, 0x1, 1280, -0x3c0000, 0x1, 0x0, 1280, -720, 0x532120, 0x1, 0x3, -0x1400, 0xcb8, -0x0, -0xfe, -0x4, 0x0, 0x0, 0x0, -0x0, 0x3c0000, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, -0x0, -0x0, 0x0 //Unknown, some timestamp perhaps? -}; - static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) { u32 *bufptr = (u32*)buf; @@ -94,9 +62,7 @@ static Result _gfxQueueBuffer(s32 buf) { static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 LayerFlags, u64 LayerId, nvServiceType nv_servicetype, size_t nv_transfermem_size) { Result rc=0; - s32 tmp=0; u32 i=0; - u64 *ptr64 = (u64*)g_gfxBufferInitData; if(g_gfxInitialized)return 0; @@ -124,23 +90,11 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L if (R_SUCCEEDED(rc)) rc = nvInitialize(nv_servicetype, nv_transfermem_size); - if (R_SUCCEEDED(rc)) rc = nvgfxInitialize(); - if (R_SUCCEEDED(rc)) rc = gfxproducerInitialize(&g_gfxBinderSession); if (R_SUCCEEDED(rc)) rc = gfxproducerConnect(2, 0); - if (R_SUCCEEDED(rc)) rc = gfxproducerQuery(2, &tmp);//"NATIVE_WINDOW_FORMAT" - - if (R_SUCCEEDED(rc)) { - for(i=0; i<2; i++) { - g_gfxBufferInitData[0xa] = i; - g_gfxBufferInitData[0x21] = 0x3c0000*i; - ptr64[0x170>>3] = svcGetSystemTick(); - rc = gfxproducerBufferInit(i, (u8*)g_gfxBufferInitData); - if (R_FAILED(rc)) break; - } - } + if (R_SUCCEEDED(rc)) rc = nvgfxInitialize(); if (R_SUCCEEDED(rc)) { for(i=0; i<2; i++) { @@ -150,16 +104,20 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L rc = gfxproducerRequestBuffer(i);//reply_parcel currently contains an error, presumably due to _gfxDequeueBuffer() failing as mentioned above. if (R_FAILED(rc)) break; + //Officially, nvioctlNvmap_FromID() and nvioctlChannel_SubmitGPFIFO() are used here. + rc = _gfxQueueBuffer(i);//reply_parcel currently contains the same error as gfxproducerRequestBuffer() above. if (R_FAILED(rc)) break; } } + if (R_SUCCEEDED(rc)) rc = nvgfxEventInit(); + if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(); if (R_FAILED(rc)) { - gfxproducerExit(); nvgfxExit(); + gfxproducerExit(); nvExit(); binderExitSession(&g_gfxBinderSession); viCloseLayer(&g_gfxLayer); @@ -197,9 +155,10 @@ void gfxInitDefault(void) { void gfxExit(void) { if(!g_gfxInitialized)return; + nvgfxExit(); + gfxproducerExit(); - nvgfxExit(); nvExit(); binderExitSession(&g_gfxBinderSession); diff --git a/nx/source/gfx/gfxproducer.c b/nx/source/gfx/gfxproducer.c index e29f54a5..b8c68b1a 100644 --- a/nx/source/gfx/gfxproducer.c +++ b/nx/source/gfx/gfxproducer.c @@ -94,7 +94,7 @@ Result gfxproducerQueueBuffer(s32 buf, u8 input[0x5c]) { parcelWriteInt32(&parcel, buf); parcelWriteData(&parcel, input, 0x5c); - rc = parcelTransact(g_gfxproducerBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply); + rc = parcelTransact(g_gfxproducerBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply); if (R_FAILED(rc)) return rc; //TODO: parse reply diff --git a/nx/source/gfx/nvgfx.c b/nx/source/gfx/nvgfx.c index 261327d8..c3cddbb1 100644 --- a/nx/source/gfx/nvgfx.c +++ b/nx/source/gfx/nvgfx.c @@ -37,6 +37,40 @@ static nvmapobj nvmap_objs[18]; static u64 nvmap_obj6_mapbuffer_xdb_offset; +static u32 g_gfxprod_BufferInitData[0x178>>2] = { +0x1, 0x16c, 0x0, +0x47424652, +1280, 720, +1280, +0x1, 0xb00, 0x2a, 0x0, +0x0, 0x51, 0xffffffff, +0x0, //nvmap handle +0x0, 0xdaffcaff, 0x2a, 0x0, +0xb00, 0x1, 0x1, 1280, +0x3c0000, 0x1, 0x0, 1280, +720, 0x532120, 0x1, 0x3, +0x1400, +0x0, //nvmap handle +0x0, +0xfe, +0x4, 0x0, 0x0, 0x0, +0x0, 0x3c0000, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, +0x0, 0x0 //Unknown, some timestamp perhaps? +}; + Result nvmapobjInitialize(nvmapobj *obj, size_t size) { Result rc=0; @@ -83,7 +117,10 @@ Result nvmapobjSetup(nvmapobj *obj, u32 heapmask, u32 flags, u32 align, u8 kind) Result nvgfxInitialize(void) { Result rc=0; - u32 pos=0; + u32 pos=0, i=0; + s32 tmp=0; + u32 tmpval=0; + u64 *ptr64 = (u64*)g_gfxprod_BufferInitData; if(g_nvgfxInitialized)return 0; u32 zcullbind_data[4] = {0x58000, 0x5, 0x2, 0x0}; @@ -151,7 +188,8 @@ Result nvgfxInitialize(void) { if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrlGpu_ZCullGetCtxSize(g_nvgfx_fd_nvhostctrlgpu, &g_nvgfx_zcullctxsize); if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrlGpu_ZCullGetInfo(g_nvgfx_fd_nvhostctrlgpu, g_nvgfx_zcullinfo); - if (R_SUCCEEDED(rc)) rc = nvQueryEvent(g_nvgfx_fd_nvhostctrlgpu, 2, &g_nvgfx_nvhostctrlgpu_event2); + //Currently broken. + //if (R_SUCCEEDED(rc)) rc = nvQueryEvent(g_nvgfx_fd_nvhostctrlgpu, 2, &g_nvgfx_nvhostctrlgpu_event2); if (R_SUCCEEDED(rc)) rc = nvOpen(&g_nvgfx_fd_nvhostasgpu, "/dev/nvhost-as-gpu"); @@ -242,7 +280,35 @@ Result nvgfxInitialize(void) { rc = nvioctlNvhostAsGpu_MapBufferEx(g_nvgfx_fd_nvhostasgpu, 0x100, pos<3 ? 0xdb : 0x86, framebuf_nvmap_handle, 0, pos*0x3c0000, 0x3c0000, nvmap_obj6_mapbuffer_xdb_offset, NULL); if (R_FAILED(rc)) break; - //Officially NVMAP_IOC_GET_ID, NVMAP_IOC_FROM_ID, NVMAP_IOC_GET_ID, and NVMAP_IOC_FROM_ID are used after the second *MapBufferEx. + if(pos==2) { + rc = gfxproducerQuery(2, &tmp);//"NATIVE_WINDOW_FORMAT" + if (R_FAILED(rc)) break; + + for(i=0; i<2; i++) { + tmpval = 0; + rc = nvioctlNvmap_GetID(g_nvgfx_fd_nvmap, nvmap_objs[6].handle, &tmpval); + if (R_FAILED(rc)) break; + + if(tmpval==~0) { + rc = 6;//official error + break; + } + + rc = nvioctlNvmap_FromID(g_nvgfx_fd_nvmap, tmpval, &tmpval); + if (R_FAILED(rc)) break; + + //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] = 0x3c0000*i; + ptr64[0x170>>3] = svcGetSystemTick(); + rc = gfxproducerBufferInit(i, (u8*)g_gfxprod_BufferInitData); + if (R_FAILED(rc)) break; + } + if (R_FAILED(rc)) break; + } } } @@ -290,17 +356,6 @@ Result nvgfxInitialize(void) { if (R_SUCCEEDED(rc)) rc = nvOpen(&g_nvgfx_fd_nvhostctrl, "/dev/nvhost-ctrl"); - if (R_SUCCEEDED(rc)) { - do { - rc = nvioctlNvhostCtrl_EventWait(g_nvgfx_fd_nvhostctrl, 0x42, 0x1ca7, 0x64, 0, &g_nvgfx_nvhostctrl_eventres); - } while(rc==5);//timeout error - } - - //Currently broken. - //if (R_SUCCEEDED(rc)) rc = nvQueryEvent(g_nvgfx_fd_nvhostctrl, g_nvgfx_nvhostctrl_eventres, &g_nvgfx_nvhostctrl_eventhandle); - - //if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrl_EventSignal(g_nvgfx_fd_nvhostctrl, g_nvgfx_nvhostctrl_eventres); - //if (R_SUCCEEDED(rc)) rc = -1; if (R_FAILED(rc)) { @@ -382,3 +437,20 @@ void nvgfxExit(void) { g_nvgfxInitialized = 0; } +Result nvgfxEventInit(void) { + Result rc=0; + + if (R_SUCCEEDED(rc)) { + do { + rc = nvioctlNvhostCtrl_EventWait(g_nvgfx_fd_nvhostctrl, 0x42, 0x1ca7, 0x64, 0, &g_nvgfx_nvhostctrl_eventres); + } while(rc==5);//timeout error + } + + //Currently broken. + //if (R_SUCCEEDED(rc)) rc = nvQueryEvent(g_nvgfx_fd_nvhostctrl, g_nvgfx_nvhostctrl_eventres, &g_nvgfx_nvhostctrl_eventhandle); + + //if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrl_EventSignal(g_nvgfx_fd_nvhostctrl, g_nvgfx_nvhostctrl_eventres); + + return rc; +} + diff --git a/nx/source/gfx/nvioctl.c b/nx/source/gfx/nvioctl.c index 26e5f5d2..bbd143a6 100644 --- a/nx/source/gfx/nvioctl.c +++ b/nx/source/gfx/nvioctl.c @@ -264,6 +264,25 @@ Result nvioctlNvmap_Create(u32 fd, u32 size, u32 *nvmap_handle) { return rc; } +Result nvioctlNvmap_FromID(u32 fd, u32 id, u32 *nvmap_handle) { + Result rc=0; + + struct { + u32 id;//in + u32 handle;//out + } data; + + memset(&data, 0, sizeof(data)); + data.id = id; + + rc = nvIoctl(fd, _IOWR(0x01, 0x03, data), &data); + if (R_FAILED(rc)) return rc; + + *nvmap_handle = data.handle; + + return rc; +} + Result nvioctlNvmap_Alloc(u32 fd, u32 nvmap_handle, u32 heapmask, u32 flags, u32 align, u8 kind, void* addr) { struct { u32 handle;//in @@ -286,6 +305,25 @@ Result nvioctlNvmap_Alloc(u32 fd, u32 nvmap_handle, u32 heapmask, u32 flags, u32 return nvIoctl(fd, _IOWR(0x01, 0x04, data), &data); } +Result nvioctlNvmap_GetID(u32 fd, u32 nvmap_handle, u32 *id) { + Result rc=0; + + struct { + u32 id;//out + u32 handle;//in + } data; + + memset(&data, 0, sizeof(data)); + data.handle = nvmap_handle; + + rc = nvIoctl(fd, _IOWR(0x01, 0x0E, data), &data); + if (R_FAILED(rc)) return rc; + + *id = data.id; + + return rc; +} + Result nvioctlChannel_SetNvmapFd(u32 fd, u32 nvmap_fd) { struct { u32 fd;//in diff --git a/nx/source/gfx/parcel.c b/nx/source/gfx/parcel.c index 95ca84fe..564d89ce 100644 --- a/nx/source/gfx/parcel.c +++ b/nx/source/gfx/parcel.c @@ -3,8 +3,12 @@ //This implements Android Parcel, hence names etc here are based on Android Parcel.cpp. -/*u8 parcel_reply_log[0x10000] = {0}; -size_t parcel_reply_log_size = 0;*/ +//#define PARCEL_LOGGING + +#ifdef PARCEL_LOGGING +u8 parcel_reply_log[0x10000] = {0}; +size_t parcel_reply_log_size = 0; +#endif void parcelInitializeContext(parcelContext *ctx) { memset(ctx, 0, sizeof(parcelContext)); @@ -44,12 +48,14 @@ Result parcelTransact(binderSession *session, u32 code, parcelContext *in_parcel memcpy(parcel_reply->ParcelData, &outparcel[outparcel32[1]], outparcel32[0]); parcel_reply->ParcelData_size = outparcel32[0]; - /*if(parcel_reply_log_size + sizeof(inparcel) + outparcel_size <= sizeof(parcel_reply_log)) { + #ifdef PARCEL_LOGGING + if(parcel_reply_log_size + sizeof(inparcel) + outparcel_size <= sizeof(parcel_reply_log)) { memcpy(&parcel_reply_log[parcel_reply_log_size], inparcel, sizeof(inparcel)); parcel_reply_log_size+= sizeof(inparcel); memcpy(&parcel_reply_log[parcel_reply_log_size], outparcel, outparcel_size); parcel_reply_log_size+= outparcel_size; - }*/ + } + #endif return 0; }