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>
typedef struct {
u32 unk_x0;
nvioctl_fence nv_fence;
u32 unk_xc[0x18>>2];
u32 is_valid;
nvioctl_fence nv_fences[4];
} PACKED bufferProducerFence;
typedef struct {

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@ extern u32 __nx_applet_type;
extern u32 g_nvgfx_totalframebufs;
extern size_t g_nvgfx_singleframebuf_size;
//TODO: Let the user configure some of this?
static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
.timestamp = 0x0,
.isAutoTimestamp = 0x1,
@ -31,27 +32,26 @@ static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
.scalingMode = 0x0,
.transform = 0x2,
.stickyTransform = 0x0,
/*.unk = {0x0, 0x1},
.unk = {0x0, 0x1},
.fence = {
.unk_x0 = 0x1,
.nv_fence = {
.id = 0x42,
.value = 0x13f4,
.is_valid = 0x1,
.nv_fences = {
{
.id = /*0x42*/0xffffffff,
.value = /*0x13f4*/0x0,
},
{0xffffffff, 0x0}, {0xffffffff, 0x0}, {0xffffffff, 0x0},
},
.unk_xc = {
0xffffffff, 0x0, 0xffffffff, 0x0, 0xffffffff, 0x0
},
}*/
}
};
static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) {
u32 *bufptr = (u32*)buf;
//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);
//bufptr = start of ParcelData
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);
//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);
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)) rc = _gfxDequeueBuffer(NULL);
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence);
/*if (R_SUCCEEDED(rc)) { //Workaround a gfx display issue.
for(i=0; i<2; i++)gfxWaitForVsync();
@ -292,6 +292,11 @@ void gfxSwapBuffers() {
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(&g_gfx_DequeueBuffer_fence);
#ifdef BUFFERSWAP_DELAY_HACK
gfxWaitForVsync();
gfxWaitForVsync();
#endif
if (R_FAILED(rc)) fatalSimple(rc);
}

View File

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