mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-27 15:22:40 +02:00
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:
parent
998980843f
commit
6569775e7d
@ -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);
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
u32 arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
|
||||
u32 impl; // 0xB (NVGPU_GPU_IMPL_GM20B)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user