mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 13:02:38 +02:00
display/gfx.h & buffer_producer.h: Start major refactor, highly WIP
This commit is contained in:
parent
10684e205a
commit
f2f59c75c0
@ -1,36 +1,31 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "../nvidia/ioctl.h"
|
||||
|
||||
typedef struct {
|
||||
u32 is_valid;
|
||||
nvioctl_fence nv_fences[4];
|
||||
} PACKED BqFence;
|
||||
#include "../nvidia/fence.h"
|
||||
|
||||
typedef struct {
|
||||
s32 left;
|
||||
s32 top;
|
||||
s32 right;
|
||||
s32 bottom;
|
||||
} PACKED BqRect;
|
||||
} BqRect;
|
||||
|
||||
typedef struct {
|
||||
s64 timestamp;
|
||||
struct { s64 timestamp; } PACKED;
|
||||
s32 isAutoTimestamp;
|
||||
BqRect crop;
|
||||
s32 scalingMode;
|
||||
u32 transform; // See the NATIVE_WINDOW_TRANSFORM_* enums.
|
||||
u32 stickyTransform;
|
||||
u32 unk[2];
|
||||
BqFence fence;
|
||||
} PACKED BqQueueBufferInput;
|
||||
NvMultiFence fence;
|
||||
} BqQueueBufferInput;
|
||||
|
||||
typedef struct {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 transformHint;
|
||||
u32 numPendingBuffers;
|
||||
} PACKED BqQueueBufferOutput;
|
||||
} BqQueueBufferOutput;
|
||||
|
||||
typedef struct {
|
||||
u32 magic;
|
||||
@ -76,18 +71,15 @@ typedef struct {
|
||||
u32 unk_x68;
|
||||
u32 buffer_size1;
|
||||
u32 unk_x70[0x33]; // Normally all-zero.
|
||||
u64 timestamp;
|
||||
} PACKED data;
|
||||
} PACKED BqGraphicBuffer;
|
||||
struct { u64 timestamp; } PACKED; // unused
|
||||
} data;
|
||||
} BqGraphicBuffer;
|
||||
|
||||
Result bqInitialize(Binder *session);
|
||||
void bqExit(void);
|
||||
|
||||
Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf);
|
||||
Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, BqFence *fence);
|
||||
Result bqDetachBuffer(s32 slot);
|
||||
Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output);
|
||||
Result bqQuery(s32 what, s32* value);
|
||||
Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output);
|
||||
Result bqDisconnect(s32 api);
|
||||
Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input);
|
||||
Result bqRequestBuffer(Binder *b, s32 bufferIdx, BqGraphicBuffer *buf);
|
||||
Result bqDequeueBuffer(Binder *b, bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, NvMultiFence *fence);
|
||||
Result bqDetachBuffer(Binder *b, s32 slot);
|
||||
Result bqQueueBuffer(Binder *b, s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output);
|
||||
Result bqQuery(Binder *b, s32 what, s32* value);
|
||||
Result bqConnect(Binder *b, s32 api, bool producerControlledByApp, BqQueueBufferOutput *output);
|
||||
Result bqDisconnect(Binder *b, s32 api);
|
||||
Result bqSetPreallocatedBuffer(Binder *b, s32 buf, BqGraphicBuffer *input);
|
||||
|
@ -17,7 +17,6 @@
|
||||
/// GfxMode set by \ref gfxSetMode. The default is GfxMode_LinearDouble. Note that the text-console (see console.h) sets this to GfxMode_TiledDouble.
|
||||
typedef enum
|
||||
{
|
||||
GfxMode_TiledSingle, ///< Single-buffering with raw tiled (block-linear) framebuffer.
|
||||
GfxMode_TiledDouble, ///< Double-buffering with raw tiled (block-linear) framebuffer.
|
||||
GfxMode_LinearDouble ///< Double-buffering with linear framebuffer, which is transferred to the actual framebuffer by \ref gfxFlushBuffers().
|
||||
} GfxMode;
|
||||
|
@ -9,7 +9,8 @@
|
||||
// Hence names/params etc here are based on Android IGraphicBufferProducer.cpp.
|
||||
|
||||
// Based on an old version of the enum from the above .cpp.
|
||||
// Unknown whether all of these are correct for Switch.
|
||||
// https://android.googlesource.com/platform/frameworks/native/+/29a3e90879fd96404c971e7187cd0e05927bbce0/libs/gui/IGraphicBufferProducer.cpp#35
|
||||
|
||||
enum {
|
||||
/* 0x1 */ REQUEST_BUFFER = BINDER_FIRST_CALL_TRANSACTION,
|
||||
/* 0x2 */ SET_BUFFER_COUNT,
|
||||
@ -24,39 +25,23 @@ enum {
|
||||
/* 0xB */ DISCONNECT,
|
||||
/* 0xC */ SET_SIDEBAND_STREAM,
|
||||
/* 0xD */ ALLOCATE_BUFFERS,
|
||||
/* 0xE */ GRAPHIC_BUFFER_INIT, // Custom Switch-specific command - unofficial name.
|
||||
/* 0xE */ SET_PREALLOCATED_BUFFER, // Custom Switch-specific command
|
||||
};
|
||||
|
||||
static char g_bq_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer";
|
||||
static const char g_bq_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer";
|
||||
|
||||
static Binder *g_bqBinderSession;
|
||||
|
||||
Result bqInitialize(Binder *session)
|
||||
{
|
||||
g_bqBinderSession = session;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bqExit(void)
|
||||
{
|
||||
g_bqBinderSession = NULL;
|
||||
}
|
||||
|
||||
Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf)
|
||||
Result bqRequestBuffer(Binder *b, s32 bufferIdx, BqGraphicBuffer *buf)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
|
||||
parcelWriteInt32(&parcel, bufferIdx);
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, REQUEST_BUFFER, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
int nonNull = parcelReadInt32(&parcel_reply);
|
||||
@ -83,14 +68,11 @@ Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf)
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, BqFence *fence)
|
||||
Result bqDequeueBuffer(Binder *b, bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, NvMultiFence *fence)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
@ -102,7 +84,7 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage,
|
||||
parcelWriteInt32(&parcel, format);
|
||||
parcelWriteUInt32(&parcel, usage);
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, DEQUEUE_BUFFER, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*buf = parcelReadInt32(&parcel_reply);
|
||||
@ -112,11 +94,11 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage,
|
||||
void* tmp_ptr;
|
||||
|
||||
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmp_size);
|
||||
if (tmp_ptr == NULL || tmp_size != sizeof(BqFence))
|
||||
if (tmp_ptr == NULL || tmp_size != sizeof(NvMultiFence))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
if (fence)
|
||||
memcpy(fence, tmp_ptr, sizeof(BqFence));
|
||||
memcpy(fence, tmp_ptr, sizeof(NvMultiFence));
|
||||
}
|
||||
|
||||
int result = parcelReadInt32(&parcel_reply);
|
||||
@ -127,21 +109,18 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage,
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqDetachBuffer(s32 slot)
|
||||
Result bqDetachBuffer(Binder *b, s32 slot)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
|
||||
parcelWriteInt32(&parcel, slot);
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, DETACH_BUFFER, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, DETACH_BUFFER, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
//TODO: parse reply
|
||||
@ -150,14 +129,11 @@ Result bqDetachBuffer(s32 slot)
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output)
|
||||
Result bqQueueBuffer(Binder *b, s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
@ -165,7 +141,7 @@ Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *ou
|
||||
parcelWriteInt32(&parcel, buf);
|
||||
parcelWriteFlattenedObject(&parcel, input, sizeof(*input));
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, QUEUE_BUFFER, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (parcelReadData(&parcel_reply, output, sizeof(*output)) == NULL)
|
||||
@ -179,21 +155,18 @@ Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *ou
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqQuery(s32 what, s32* value)
|
||||
Result bqQuery(Binder *b, s32 what, s32* value)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
|
||||
parcelWriteInt32(&parcel, what);
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, QUERY, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, QUERY, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*value = parcelReadInt32(&parcel_reply);
|
||||
@ -206,14 +179,11 @@ Result bqQuery(s32 what, s32* value)
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output)
|
||||
Result bqConnect(Binder *b, s32 api, bool producerControlledByApp, BqQueueBufferOutput *output)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
@ -224,7 +194,7 @@ Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *out
|
||||
parcelWriteInt32(&parcel, api);
|
||||
parcelWriteInt32(&parcel, producerControlledByApp);
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, CONNECT, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, CONNECT, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (parcelReadData(&parcel_reply, output, sizeof(*output)) == NULL)
|
||||
@ -238,21 +208,18 @@ Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *out
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqDisconnect(s32 api)
|
||||
Result bqDisconnect(Binder *b, s32 api)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
|
||||
parcelWriteInt32(&parcel, api);
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, DISCONNECT, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, DISCONNECT, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
// TODO: parse reply
|
||||
@ -261,15 +228,12 @@ Result bqDisconnect(s32 api)
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input)
|
||||
Result bqSetPreallocatedBuffer(Binder *b, s32 buf, BqGraphicBuffer *input)
|
||||
{
|
||||
Result rc;
|
||||
Parcel parcel, parcel_reply;
|
||||
bool flag = 0;
|
||||
|
||||
if (g_bqBinderSession == NULL)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
|
||||
parcelCreate(&parcel);
|
||||
parcelCreate(&parcel_reply);
|
||||
|
||||
@ -283,7 +247,7 @@ Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input)
|
||||
if (flag)
|
||||
parcelWriteFlattenedObject(&parcel, input, sizeof(BqGraphicBuffer));
|
||||
|
||||
rc = parcelTransact(g_bqBinderSession, GRAPHIC_BUFFER_INIT, &parcel, &parcel_reply);
|
||||
rc = parcelTransact(b, SET_PREALLOCATED_BUFFER, &parcel, &parcel_reply);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
int result = parcelReadInt32(&parcel_reply);
|
||||
|
@ -20,11 +20,10 @@ static Binder g_gfxBinderSession;
|
||||
static s32 g_gfxCurrentBuffer = 0;
|
||||
static s32 g_gfxCurrentProducerBuffer = 0;
|
||||
static bool g_gfx_ProducerConnected = 0;
|
||||
static bool g_gfx_ProducerSlotsRequested[2] = {0, 0};
|
||||
static u32 g_gfx_ProducerSlotsRequested = 0;
|
||||
static u8 *g_gfxFramebuf;
|
||||
static size_t g_gfxFramebufSize;
|
||||
static u32 g_gfxFramebufHandle;
|
||||
static BqFence g_gfx_DequeueBuffer_fence;
|
||||
static BqQueueBufferOutput g_gfx_Connect_QueueBufferOutput;
|
||||
static BqQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput;
|
||||
|
||||
@ -51,7 +50,6 @@ static s32 g_gfx_autoresolution_docked_height;
|
||||
extern u32 __nx_applet_type;
|
||||
|
||||
extern u32 g_nvgfx_totalframebufs;
|
||||
extern nvioctl_fence g_nvgfx_nvhostgpu_gpfifo_fence;
|
||||
|
||||
//static Result _gfxGetDisplayResolution(u64 *width, u64 *height);
|
||||
|
||||
@ -64,17 +62,7 @@ static BqQueueBufferInput g_gfxQueueBufferData = {
|
||||
.transform = NATIVE_WINDOW_TRANSFORM_FLIP_V,
|
||||
.stickyTransform = 0x0,
|
||||
.unk = {0x0, 0x1},
|
||||
|
||||
.fence = {
|
||||
.is_valid = 0x1,
|
||||
.nv_fences = {
|
||||
{
|
||||
.id = 0xffffffff, //Official sw sets this to the output fence from the last nvioctlChannel_SubmitGPFIFO().
|
||||
.value = 0x0,
|
||||
},
|
||||
{0xffffffff, 0x0}, {0xffffffff, 0x0}, {0xffffffff, 0x0},
|
||||
},
|
||||
}
|
||||
.fence = {0},
|
||||
};
|
||||
|
||||
// Some of this struct is based on tegra_dc_ext_flip_windowattr.
|
||||
@ -108,50 +96,56 @@ static BqGraphicBuffer g_gfx_BufferInitData = {
|
||||
}
|
||||
};
|
||||
|
||||
static Result _gfxDequeueBuffer(void) {
|
||||
Result rc=0;
|
||||
BqFence *fence = &g_gfx_DequeueBuffer_fence;
|
||||
BqFence tmp_fence;
|
||||
bool async=0;
|
||||
NvMultiFence debugfence;
|
||||
Result debugfenceresult;
|
||||
|
||||
if (g_gfxMode == GfxMode_TiledSingle) {
|
||||
g_gfxCurrentProducerBuffer = -1;
|
||||
static Result _gfxDequeueBuffer(void) {
|
||||
if (g_gfxCurrentProducerBuffer >= 0)
|
||||
return 0;
|
||||
|
||||
NvMultiFence fence;
|
||||
s32 slot;
|
||||
Result rc = bqDequeueBuffer(&g_gfxBinderSession, false, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &slot, &fence);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
|
||||
if (!(g_gfx_ProducerSlotsRequested & BIT(slot))) {
|
||||
rc = bqRequestBuffer(&g_gfxBinderSession, slot, NULL);
|
||||
if (R_FAILED(rc))
|
||||
return rc; // todo: cancelbuffer or something
|
||||
g_gfx_ProducerSlotsRequested |= BIT(slot);
|
||||
}
|
||||
|
||||
memcpy(&tmp_fence, fence, sizeof(BqFence));//Offical sw waits on the fence from the previous DequeueBuffer call. Using the fence from the current DequeueBuffer call results in nvgfxEventWait() failing.
|
||||
debugfence = fence;
|
||||
for (u32 i = 0; i < fence.num_fences; i ++) {
|
||||
if ((s32)fence.fences[i].id >= 0) {
|
||||
// todo: figure out why fencewait sucks
|
||||
/*rc =*/ debugfenceresult = nvgfxEventWait(fence.fences[i].id, fence.fences[i].value, 0);
|
||||
//if (R_FAILED(rc))
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
rc = bqDequeueBuffer(async, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &g_gfxCurrentProducerBuffer, fence);
|
||||
|
||||
//Only run nvgfxEventWait when the fence is valid and the id is not NO_FENCE.
|
||||
if (R_SUCCEEDED(rc) && tmp_fence.is_valid && tmp_fence.nv_fences[0].id!=0xffffffff) rc = nvgfxEventWait(tmp_fence.nv_fences[0].id, tmp_fence.nv_fences[0].value, -1);
|
||||
|
||||
if (R_SUCCEEDED(rc)) g_gfxCurrentBuffer = (g_gfxCurrentBuffer + 1) & (g_nvgfx_totalframebufs-1);
|
||||
|
||||
//if (R_SUCCEEDED(rc)) rc = nvgfxSubmitGpfifo();
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
g_gfxCurrentProducerBuffer = slot;
|
||||
g_gfxCurrentBuffer = g_gfxCurrentProducerBuffer;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _gfxQueueBuffer(s32 buf) {
|
||||
static Result _gfxQueueBuffer(void) {
|
||||
Result rc=0;
|
||||
|
||||
if (buf == -1) return 0;
|
||||
|
||||
g_gfxQueueBufferData.timestamp = svcGetSystemTick();//This is probably not the proper value for the timestamp, but shouldn't(?) matter.
|
||||
//if (g_nvgfx_nvhostgpu_gpfifo_fence.id) memcpy(&g_gfxQueueBufferData.fence.nv_fences[0], &g_nvgfx_nvhostgpu_gpfifo_fence, sizeof(nvioctl_fence));
|
||||
//if (g_nvgfx_nvhostgpu_gpfifo_fence.id) rc = nvgfxEventWait(g_nvgfx_nvhostgpu_gpfifo_fence.id, g_nvgfx_nvhostgpu_gpfifo_fence.value, -1);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
|
||||
rc = bqQueueBuffer(buf, &g_gfxQueueBufferData, &g_gfx_QueueBuffer_QueueBufferOutput);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
if (g_gfxCurrentProducerBuffer >= 0) {
|
||||
rc = bqQueueBuffer(&g_gfxBinderSession, g_gfxCurrentProducerBuffer, &g_gfxQueueBufferData, &g_gfx_QueueBuffer_QueueBufferOutput);
|
||||
g_gfxCurrentProducerBuffer = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result gfxInitDefault(void) {
|
||||
Result rc=0;
|
||||
u32 i=0;
|
||||
|
||||
if(g_gfxInitialized)return 0;
|
||||
|
||||
@ -167,8 +161,8 @@ Result gfxInitDefault(void) {
|
||||
g_gfx_drawflip = true;
|
||||
g_gfxQueueBufferData.transform = NATIVE_WINDOW_TRANSFORM_FLIP_V;
|
||||
|
||||
memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested));
|
||||
memset(&g_gfx_DequeueBuffer_fence, 0, sizeof(g_gfx_DequeueBuffer_fence));
|
||||
//memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested));
|
||||
g_gfx_ProducerSlotsRequested = 0;
|
||||
|
||||
if (g_gfx_framebuf_width==0 || g_gfx_framebuf_height==0) {
|
||||
g_gfx_framebuf_width = 1280;
|
||||
@ -214,68 +208,39 @@ Result gfxInitDefault(void) {
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = viCreateLayer(&g_gfxDisplay, &g_gfxLayer);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = viSetLayerScalingMode(&g_gfxLayer, ViScalingMode_Default);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
binderCreate(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxLayer.igbp_binder_obj_id);
|
||||
rc = binderInitSession(&g_gfxBinderSession, 0x0f);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = viSetLayerScalingMode(&g_gfxLayer, ViScalingMode_Default);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = bqConnect(&g_gfxBinderSession, NATIVE_WINDOW_API_CPU, 0, &g_gfx_Connect_QueueBufferOutput);
|
||||
|
||||
if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = true;
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = nvInitialize();
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = bqInitialize(&g_gfxBinderSession);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = bqConnect(NATIVE_WINDOW_API_CPU, 0, &g_gfx_Connect_QueueBufferOutput);
|
||||
|
||||
if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = 1;
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = nvgfxInitialize();
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = nvgfxGetFramebuffer(&g_gfxFramebuf, &g_gfxFramebufSize, &g_gfxFramebufHandle);
|
||||
|
||||
if (R_SUCCEEDED(rc)) { //Official sw would use bqRequestBuffer() when required during swap-buffers/or similar, but that's not really an option here due to gfxSetDoubleBuffering().
|
||||
for(i=0; i<2; i++) {
|
||||
rc = _gfxDequeueBuffer();
|
||||
if (R_FAILED(rc)) break;
|
||||
|
||||
rc = bqRequestBuffer(g_gfxCurrentProducerBuffer, NULL);
|
||||
if (R_FAILED(rc)) break;
|
||||
|
||||
g_gfx_ProducerSlotsRequested[i] = 1;
|
||||
|
||||
//Officially, nvioctlNvmap_FromID() and nvioctlChannel_SubmitGPFIFO() are used here.
|
||||
|
||||
rc = _gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
||||
if (R_FAILED(rc)) {
|
||||
g_gfxCurrentProducerBuffer = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = _gfxDequeueBuffer();
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (__nx_applet_type == AppletType_Application) { //It's unknown whether there's a better way to handle this.
|
||||
svcSleepThread(2000000000);
|
||||
}
|
||||
else {
|
||||
for(i=0; i<2; i++) gfxWaitForVsync();
|
||||
}
|
||||
}
|
||||
// todo: figure out if it's possible to wait for the 'Nintendo' logo screen to finish displaying (NSO, applet type: Application)
|
||||
|
||||
if (R_FAILED(rc)) {
|
||||
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
||||
for(i=0; i<2; i++) {
|
||||
if (g_gfx_ProducerSlotsRequested[i]) bqDetachBuffer(i);
|
||||
if (g_gfx_ProducerConnected) {
|
||||
_gfxQueueBuffer();
|
||||
for(u32 i=0; i<32; i++) {
|
||||
if (g_gfx_ProducerSlotsRequested & BIT(i)) bqDetachBuffer(&g_gfxBinderSession, i);
|
||||
}
|
||||
if (g_gfx_ProducerConnected) bqDisconnect(NATIVE_WINDOW_API_CPU);
|
||||
|
||||
bqDisconnect(&g_gfxBinderSession, NATIVE_WINDOW_API_CPU);
|
||||
nvgfxExit();
|
||||
bqExit();
|
||||
binderClose(&g_gfxBinderSession);
|
||||
nvExit();
|
||||
}
|
||||
|
||||
binderClose(&g_gfxBinderSession);
|
||||
viCloseLayer(&g_gfxLayer);
|
||||
viCloseDisplay(&g_gfxDisplay);
|
||||
viExit();
|
||||
@ -298,7 +263,7 @@ Result gfxInitDefault(void) {
|
||||
g_gfx_framebuf_width = 0;
|
||||
g_gfx_framebuf_height = 0;
|
||||
|
||||
memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested));
|
||||
g_gfx_ProducerSlotsRequested = 0;
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) g_gfxInitialized = 1;
|
||||
@ -308,34 +273,29 @@ Result gfxInitDefault(void) {
|
||||
|
||||
void gfxExit(void)
|
||||
{
|
||||
u32 i = 0;
|
||||
if (!g_gfxInitialized)
|
||||
return;
|
||||
|
||||
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
||||
for (i=0; i<2; i++) {
|
||||
if (g_gfx_ProducerSlotsRequested[i]) bqDetachBuffer(i);
|
||||
if (g_gfx_ProducerConnected) {
|
||||
_gfxQueueBuffer();
|
||||
for(u32 i=0; i<32; i++) {
|
||||
if (g_gfx_ProducerSlotsRequested & BIT(i)) bqDetachBuffer(&g_gfxBinderSession, i);
|
||||
}
|
||||
if (g_gfx_ProducerConnected) bqDisconnect(2);
|
||||
|
||||
bqDisconnect(&g_gfxBinderSession, NATIVE_WINDOW_API_CPU);
|
||||
nvgfxExit();
|
||||
|
||||
bqExit();
|
||||
binderClose(&g_gfxBinderSession);
|
||||
|
||||
nvExit();
|
||||
}
|
||||
|
||||
binderClose(&g_gfxBinderSession);
|
||||
viCloseLayer(&g_gfxLayer);
|
||||
viCloseDisplay(&g_gfxDisplay);
|
||||
viExit();
|
||||
|
||||
if(g_gfxDisplayVsyncEvent != INVALID_HANDLE) {
|
||||
svcCloseHandle(g_gfxDisplayVsyncEvent);
|
||||
g_gfxDisplayVsyncEvent = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
viCloseDisplay(&g_gfxDisplay);
|
||||
|
||||
viExit();
|
||||
|
||||
free(g_gfxFramebufLinear);
|
||||
g_gfxFramebufLinear = NULL;
|
||||
|
||||
@ -352,8 +312,7 @@ void gfxExit(void)
|
||||
|
||||
gfxConfigureAutoResolution(0, 0, 0, 0, 0);
|
||||
|
||||
memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested));
|
||||
|
||||
g_gfx_ProducerSlotsRequested = 0;
|
||||
memset(&g_gfxQueueBufferData.crop, 0, sizeof(g_gfxQueueBufferData.crop));
|
||||
}
|
||||
|
||||
@ -442,33 +401,29 @@ Result _gfxGraphicBufferInit(s32 buf, u32 nvmap_id, u32 nvmap_handle) {
|
||||
g_gfx_BufferInitData.data.buffer_offset = g_gfx_singleframebuf_size*buf;
|
||||
g_gfx_BufferInitData.data.timestamp = svcGetSystemTick();
|
||||
|
||||
return bqGraphicBufferInit(buf, &g_gfx_BufferInitData);
|
||||
return bqSetPreallocatedBuffer(&g_gfxBinderSession, buf, &g_gfx_BufferInitData);
|
||||
}
|
||||
|
||||
static void _waitevent(Handle *handle) {
|
||||
Result rc=0, rc2=0;
|
||||
|
||||
svcResetSignal(*handle);
|
||||
static void _waitevent(Handle handle) {
|
||||
Result rc;
|
||||
|
||||
do {
|
||||
rc = svcWaitSynchronizationSingle(*handle, U64_MAX);
|
||||
rc = svcWaitSynchronizationSingle(handle, U64_MAX);
|
||||
svcResetSignal(handle);
|
||||
} while ((rc & 0x3FFFFF) == 0xFA01);
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc2 = svcResetSignal(*handle);
|
||||
|
||||
} while(R_FAILED(rc) || (rc2 & 0x3FFFFF)==0xFA01);
|
||||
|
||||
if (R_FAILED(rc2)) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadGfxEventWait));
|
||||
if (R_FAILED(rc))
|
||||
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadGfxEventWait));
|
||||
}
|
||||
|
||||
void gfxWaitForVsync(void) {
|
||||
_waitevent(&g_gfxDisplayVsyncEvent);
|
||||
_waitevent(g_gfxDisplayVsyncEvent);
|
||||
}
|
||||
|
||||
void gfxSwapBuffers(void) {
|
||||
Result rc=0;
|
||||
|
||||
rc = _gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
||||
rc = _gfxQueueBuffer();
|
||||
|
||||
if (R_FAILED(rc)) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_BadGfxQueueBuffer));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user