Added parcelReadFlattenedObject/parcelWriteFlattenedObject. Parse bufferProducerDequeueBuffer output properly. Handle bufferProducerQueueBuffer input/output properly. Updated vsync handling. Added a 3s delay for gfx-init. Updated g_gfxQueueBufferData, etc.

This commit is contained in:
yellows8 2017-12-02 18:50:47 -05:00
parent 998980843f
commit 6569775e7d
6 changed files with 122 additions and 33 deletions

View File

@ -1,10 +1,38 @@
#pragma once
#include <switch/gfx/nvioctl.h>
typedef struct {
u32 unk_x0;
nvioctl_fence nv_fence;
u32 unk_xc[0x18>>2];
} PACKED bufferProducerFence;
typedef struct {
s64 timestamp;
s32 isAutoTimestamp;
u32 crop[4];//Rect
s32 scalingMode;
u32 transform;
u32 stickyTransform;
u32 unk[2];
bufferProducerFence fence;
} PACKED bufferProducerQueueBufferInput;
typedef struct {
u32 width;
u32 height;
u32 transformHint;
u32 numPendingBuffers;
} PACKED bufferProducerQueueBufferOutput;
Result bufferProducerInitialize(binderSession *session);
void bufferProducerExit();
Result bufferProducerRequestBuffer(s32 bufferIdx);
Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *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, u8 input[0x5c]);
Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input, bufferProducerQueueBufferOutput *output);
Result bufferProducerQuery(s32 what, s32* value);
Result bufferProducerConnect(s32 api, bool producerControlledByApp);
Result bufferProducerDisconnect(s32 api);

View File

@ -1,3 +1,5 @@
#pragma once
typedef struct {
u32 arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
u32 impl; // 0xB (NVGPU_GPU_IMPL_GM20B)

View File

@ -25,3 +25,6 @@ s32 parcelReadInt32(Parcel *ctx);
u32 parcelReadUInt32(Parcel *ctx);
void parcelWriteInterfaceToken(Parcel *ctx, const char *str);
void* parcelReadFlattenedObject(Parcel *ctx, size_t *size);
void* parcelWriteFlattenedObject(Parcel *ctx, void* data, size_t size);

View File

@ -74,7 +74,7 @@ Result bufferProducerRequestBuffer(s32 bufferIdx)
return rc;
}
Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf)
Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, bufferProducerFence *fence)
{
Result rc;
Parcel parcel, parcel_reply;
@ -96,8 +96,20 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format
rc = parcelTransact(g_bufferProducerBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) {
// TODO: parse reply
*buf = parcelReadInt32(&parcel_reply);
if(parcelReadInt32(&parcel_reply)) {
size_t tmpsize=0;
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);
}
int result = parcelReadInt32(&parcel_reply);
if (result != 0)
rc = MAKERESULT(MODULE_LIBNX, LIBNX_BUFFERPRODUCER_ERROR);
}
return rc;
@ -126,7 +138,7 @@ Result bufferProducerDetachBuffer(s32 slot)
return rc;
}
Result bufferProducerQueueBuffer(s32 buf, u8 input[0x5c])
Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input, bufferProducerQueueBufferOutput *output)
{
Result rc;
Parcel parcel, parcel_reply;
@ -139,12 +151,16 @@ Result bufferProducerQueueBuffer(s32 buf, u8 input[0x5c])
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf);
parcelWriteData(&parcel, input, 0x5c);
parcelWriteFlattenedObject(&parcel, input, sizeof(bufferProducerQueueBufferInput));
rc = parcelTransact(g_bufferProducerBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) {
//TODO: parse reply
if (parcelReadData(&parcel_reply, output, sizeof(bufferProducerQueueBufferOutput))==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_BADINPUT);
int result = parcelReadInt32(&parcel_reply);
if (result != 0)
rc = MAKERESULT(MODULE_LIBNX, LIBNX_BUFFERPRODUCER_ERROR);
}
return rc;

View File

@ -23,16 +23,26 @@ extern u32 __nx_applet_type;
extern u32 g_nvgfx_totalframebufs;
extern size_t g_nvgfx_singleframebuf_size;
static u32 g_gfxQueueBufferData[0x5c>>2] = {
0x54, 0x0,
0x0, 0x0, //u64 timestamp
0x1, 0x0, 0x0,
0x0, 0x0, 0x0, 0x2,
0x0, 0x0, 0x1, 0x1,
0x42,
0x13f4,
0xffffffff, 0x0,
0xffffffff, 0x0, 0xffffffff, 0x0};
static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
.timestamp = 0x0,
.isAutoTimestamp = 0x1,
.crop = {0x0, 0x0, 0x0, 0x0},
.scalingMode = 0x0,
.transform = 0x2,
.stickyTransform = 0x0,
/*.unk = {0x0, 0x1},
.fence = {
.unk_x0 = 0x1,
.nv_fence = {
.id = 0x42,
.value = 0x13f4,
},
.unk_xc = {
0xffffffff, 0x0, 0xffffffff, 0x0, 0xffffffff, 0x0
},
}*/
};
static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) {
u32 *bufptr = (u32*)buf;
@ -49,7 +59,7 @@ static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) {
return 0;
}
static Result _gfxDequeueBuffer() {
static Result _gfxDequeueBuffer(bufferProducerFence *fence) {
Result rc=0;
if (!g_gfxDoubleBuf) {
@ -57,7 +67,7 @@ static Result _gfxDequeueBuffer() {
return 0;
}
rc = bufferProducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer);
rc = bufferProducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer, fence);
if (R_SUCCEEDED(rc)) g_gfxCurrentBuffer = (g_gfxCurrentBuffer + 1) & (g_nvgfx_totalframebufs-1);
@ -66,19 +76,18 @@ static Result _gfxDequeueBuffer() {
static Result _gfxQueueBuffer(s32 buf) {
Result rc=0;
u64 *ptr64 = (u64*)&g_gfxQueueBufferData;
if (buf == -1) return 0;
ptr64[1] = svcGetSystemTick();//Unknown what is actually used for timestamp, but shouldn't(?) matter.
g_gfxQueueBufferData.timestamp = svcGetSystemTick();//This is probably not the proper value for the timestamp, but shouldn't(?) matter.
rc = bufferProducerQueueBuffer(buf, (u8*)g_gfxQueueBufferData);
rc = bufferProducerQueueBuffer(buf, &g_gfxQueueBufferData, NULL);
if (R_FAILED(rc)) return rc;
/*if(buf==0) {
g_gfxQueueBufferData[0x10]+= 0x6;
/*if(buf==0) {//
g_gfxQueueBufferData.nv_fence.value+= 0x6;
} else {
g_gfxQueueBufferData[0x10]+= 0x7;
g_gfxQueueBufferData.nv_fence.value+= 0x7;
}*/
return rc;
@ -133,7 +142,7 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L
if (R_SUCCEEDED(rc)) {
for(i=0; i<2; i++) {
rc = _gfxDequeueBuffer();
rc = _gfxDequeueBuffer(NULL);
if (R_FAILED(rc)) break;
rc = bufferProducerRequestBuffer(g_gfxCurrentProducerBuffer);
@ -153,11 +162,13 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L
if (R_SUCCEEDED(rc)) rc = nvgfxEventInit();
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer();
if (R_SUCCEEDED(rc)) svcSleepThread(3000000000);
if (R_SUCCEEDED(rc)) { //Workaround a gfx display issue.
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(NULL);
/*if (R_SUCCEEDED(rc)) { //Workaround a gfx display issue.
for(i=0; i<2; i++)gfxWaitForVsync();
}
}*/
if (R_FAILED(rc)) {
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
@ -257,10 +268,20 @@ void gfxExit(void) {
memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested));
}
static void _waitevent(Handle *handle) {
s32 tmpindex=0;
Result rc=0, rc2=0;
do {
rc = svcWaitSynchronization(&tmpindex, handle, 1, U64_MAX);
if (R_SUCCEEDED(rc)) rc2 = svcResetSignal(*handle);
} while(R_FAILED(rc) || (rc2 & 0x3FFFFF)==0xFA01);
if (R_FAILED(rc2)) fatalSimple(rc2);
}
void gfxWaitForVsync() {
s32 tmp = 0;
svcWaitSynchronization(&tmp, &g_gfxDisplayVsyncEvent, 1, U64_MAX);
svcClearEvent(g_gfxDisplayVsyncEvent);
_waitevent(&g_gfxDisplayVsyncEvent);
}
void gfxSwapBuffers() {
@ -268,7 +289,7 @@ void gfxSwapBuffers() {
rc = _gfxQueueBuffer(g_gfxCurrentProducerBuffer);
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer();
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer(NULL);
if (R_FAILED(rc)) fatalSimple(rc);
}

View File

@ -142,3 +142,22 @@ u32 parcelReadUInt32(Parcel *ctx) {
parcelReadData(ctx, &val, sizeof(val));
return val;
}
void* parcelReadFlattenedObject(Parcel *ctx, size_t *size) {
s32 len = parcelReadInt32(ctx);
s32 fd_count = parcelReadInt32(ctx);
if (size) *size = (u32)len;
if(fd_count!=0)return NULL;//Not going to support fds.
return parcelReadData(ctx, NULL, len);
}
void* parcelWriteFlattenedObject(Parcel *ctx, void* data, size_t size) {
parcelWriteInt32(ctx, size);//len
parcelWriteInt32(ctx, 0);//fd_count
return parcelWriteData(ctx, data, size);
}