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; }