Updated bufferProducerFence. Updated nvgfxEventWait. Added better initialization validation to binder, etc. In bufferProducerDequeueBuffer(), use sizeof instead of a constant for the fence size. Updated g_gfxQueueBufferData. Fixed validation in _gfxGetNativeWindowID. Other changes.

This commit is contained in:
yellows8 2017-12-03 22:39:46 -05:00
parent 428d0373a8
commit 63016db072
7 changed files with 59 additions and 29 deletions

View File

@ -3,9 +3,8 @@
#include <switch/gfx/nvioctl.h> #include <switch/gfx/nvioctl.h>
typedef struct { typedef struct {
u32 unk_x0; u32 is_valid;
nvioctl_fence nv_fence; nvioctl_fence nv_fences[4];
u32 unk_xc[0x18>>2];
} PACKED bufferProducerFence; } PACKED bufferProducerFence;
typedef struct { typedef struct {

View File

@ -1,4 +1,4 @@
Result nvgfxInitialize(void); Result nvgfxInitialize(void);
void nvgfxExit(void); void nvgfxExit(void);
Result nvgfxEventInit(void); Result nvgfxEventWait(u32 syncpt_id, u32 threshold);
Result nvgfxGetFramebuffer(u8 **buffer, size_t *size); Result nvgfxGetFramebuffer(u8 **buffer, size_t *size);

View File

@ -1,6 +1,8 @@
#define BINDER_FIRST_CALL_TRANSACTION 0x1 #define BINDER_FIRST_CALL_TRANSACTION 0x1
typedef struct { typedef struct {
bool created;
bool initialized;
Handle sessionHandle; Handle sessionHandle;
s32 id; s32 id;
Handle nativeHandle; Handle nativeHandle;

View File

@ -4,6 +4,7 @@
void binderCreateSession(binderSession *session, Handle sessionHandle, s32 id) void binderCreateSession(binderSession *session, Handle sessionHandle, s32 id)
{ {
memset(session, 0, sizeof(binderSession)); memset(session, 0, sizeof(binderSession));
session->created = 1;
session->sessionHandle = sessionHandle; session->sessionHandle = sessionHandle;
session->id = id; session->id = id;
session->nativeHandle = INVALID_HANDLE; session->nativeHandle = INVALID_HANDLE;
@ -14,6 +15,9 @@ Result binderInitSession(binderSession *session, u32 unk0)
{ {
Result rc = 0; Result rc = 0;
if (!session->created) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
if (session->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_ALREADYINITIALIZED);
rc = binderAdjustRefcount(session, 1, 0); rc = binderAdjustRefcount(session, 1, 0);
if (R_FAILED(rc)) if (R_FAILED(rc))
@ -41,6 +45,8 @@ Result binderInitSession(binderSession *session, u32 unk0)
return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT);
} }
session->initialized = 1;
rc = ipcQueryPointerBufferSize(session->sessionHandle, &session->ipcBufferSize); rc = ipcQueryPointerBufferSize(session->sessionHandle, &session->ipcBufferSize);
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
@ -57,6 +63,9 @@ Result binderInitSession(binderSession *session, u32 unk0)
void binderExitSession(binderSession *session) void binderExitSession(binderSession *session)
{ {
if (!session->created) return;
if (session->initialized) {
binderAdjustRefcount(session, -1, 1); binderAdjustRefcount(session, -1, 1);
binderAdjustRefcount(session, -1, 0); binderAdjustRefcount(session, -1, 0);
@ -66,12 +75,21 @@ void binderExitSession(binderSession *session)
} }
} }
session->sessionHandle = INVALID_HANDLE;
session->id = 0;
session->created = 0;
session->initialized = 0;
}
static Result _binderTransactParcel( static Result _binderTransactParcel(
binderSession *session, u32 code, binderSession *session, u32 code,
void* parcel_data, size_t parcel_data_size, void* parcel_data, size_t parcel_data_size,
void* parcel_reply, size_t parcel_reply_size, void* parcel_reply, size_t parcel_reply_size,
u32 flags) u32 flags)
{ {
if (!session->created || !session->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -116,6 +134,8 @@ static Result _binderTransactParcelAuto(
void* parcel_reply, size_t parcel_reply_size, void* parcel_reply, size_t parcel_reply_size,
u32 flags) u32 flags)
{ {
if (!session->created || !session->initialized) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -193,6 +213,8 @@ Result binderTransactParcel(
Result binderAdjustRefcount(binderSession *session, s32 addval, s32 type) Result binderAdjustRefcount(binderSession *session, s32 addval, s32 type)
{ {
if (!session->created) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -230,6 +252,8 @@ Result binderAdjustRefcount(binderSession *session, s32 addval, s32 type)
Result binderGetNativeHandle(binderSession *session, u32 inval, Handle *handle_out) Result binderGetNativeHandle(binderSession *session, u32 inval, Handle *handle_out)
{ {
if (!session->created) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);

View File

@ -103,8 +103,8 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format
void* tmp_ptr; void* tmp_ptr;
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize); tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize);
if (tmp_ptr==NULL || tmpsize!=0x24) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerFence)) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT);
if (fence) memcpy(fence, tmp_ptr, 0x24); if (fence) memcpy(fence, tmp_ptr, sizeof(bufferProducerFence));
} }
int result = parcelReadInt32(&parcel_reply); int result = parcelReadInt32(&parcel_reply);

View File

@ -24,6 +24,7 @@ extern u32 __nx_applet_type;
extern u32 g_nvgfx_totalframebufs; extern u32 g_nvgfx_totalframebufs;
extern size_t g_nvgfx_singleframebuf_size; extern size_t g_nvgfx_singleframebuf_size;
//TODO: Let the user configure some of this?
static bufferProducerQueueBufferInput g_gfxQueueBufferData = { static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
.timestamp = 0x0, .timestamp = 0x0,
.isAutoTimestamp = 0x1, .isAutoTimestamp = 0x1,
@ -31,27 +32,26 @@ static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
.scalingMode = 0x0, .scalingMode = 0x0,
.transform = 0x2, .transform = 0x2,
.stickyTransform = 0x0, .stickyTransform = 0x0,
/*.unk = {0x0, 0x1}, .unk = {0x0, 0x1},
.fence = { .fence = {
.unk_x0 = 0x1, .is_valid = 0x1,
.nv_fence = { .nv_fences = {
.id = 0x42, {
.value = 0x13f4, .id = /*0x42*/0xffffffff,
.value = /*0x13f4*/0x0,
}, },
.unk_xc = { {0xffffffff, 0x0}, {0xffffffff, 0x0}, {0xffffffff, 0x0},
0xffffffff, 0x0, 0xffffffff, 0x0, 0xffffffff, 0x0
}, },
}*/ }
}; };
static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) { static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) {
u32 *bufptr = (u32*)buf; u32 *bufptr = (u32*)buf;
//Validate ParcelData{Size|Offset}. //Validate ParcelData{Size|Offset}.
if((u64)bufptr[1] >= size || (u64)bufptr[0] >= size || ((u64)bufptr[1])+((u64)bufptr[0]) >= size) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); if((u64)bufptr[1] > size || (u64)bufptr[0] > size || ((u64)bufptr[1])+((u64)bufptr[0]) > size) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT);
if(bufptr[0] < 0xc) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT); if(bufptr[0] < 0xc) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT);
//bufptr = start of ParcelData //bufptr = start of ParcelData
bufptr = (u32*)&buf[bufptr[1]]; bufptr = (u32*)&buf[bufptr[1]];
@ -70,6 +70,8 @@ static Result _gfxDequeueBuffer(bufferProducerFence *fence) {
rc = bufferProducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer, fence); rc = bufferProducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer, fence);
//if (R_SUCCEEDED(rc) && fence) rc = nvgfxEventWait(fence->nv_fences[0].id, fence->nv_fences[0].value);
if (R_SUCCEEDED(rc)) g_gfxCurrentBuffer = (g_gfxCurrentBuffer + 1) & (g_nvgfx_totalframebufs-1); if (R_SUCCEEDED(rc)) g_gfxCurrentBuffer = (g_gfxCurrentBuffer + 1) & (g_nvgfx_totalframebufs-1);
return rc; return rc;
@ -161,11 +163,9 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L
} }
} }
if (R_SUCCEEDED(rc)) rc = nvgfxEventInit();
if (R_SUCCEEDED(rc)) svcSleepThread(3000000000); if (R_SUCCEEDED(rc)) svcSleepThread(3000000000);
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(NULL); if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence);
/*if (R_SUCCEEDED(rc)) { //Workaround a gfx display issue. /*if (R_SUCCEEDED(rc)) { //Workaround a gfx display issue.
for(i=0; i<2; i++)gfxWaitForVsync(); for(i=0; i<2; i++)gfxWaitForVsync();
@ -292,6 +292,11 @@ void gfxSwapBuffers() {
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence); if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence);
#ifdef BUFFERSWAP_DELAY_HACK
gfxWaitForVsync();
gfxWaitForVsync();
#endif
if (R_FAILED(rc)) fatalSimple(rc); if (R_FAILED(rc)) fatalSimple(rc);
} }

View File

@ -442,14 +442,14 @@ void nvgfxExit(void) {
g_nvgfxInitialized = 0; g_nvgfxInitialized = 0;
} }
Result nvgfxEventInit(void) { Result nvgfxEventWait(u32 syncpt_id, u32 threshold) {
Result rc=0; Result rc=0;
/*if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
do { do {
rc = nvioctlNvhostCtrl_EventWait(g_nvgfx_fd_nvhostctrl, 0x42, 0x1ca7, 0x64, 0, &g_nvgfx_nvhostctrl_eventres); rc = nvioctlNvhostCtrl_EventWait(g_nvgfx_fd_nvhostctrl, /*0x42, 0x1ca7*/syncpt_id, threshold, 0x64, 0, &g_nvgfx_nvhostctrl_eventres);
} while(rc==5);//timeout error } while(rc==5);//timeout error
}*/ }
//Currently broken. //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 = nvQueryEvent(g_nvgfx_fd_nvhostctrl, g_nvgfx_nvhostctrl_eventres, &g_nvgfx_nvhostctrl_eventhandle);