mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-28 07:42:55 +02:00
More refactoring, renamed graphicsproducer -> bufferproducer
This commit is contained in:
parent
7f2135754a
commit
806a75c841
@ -38,7 +38,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <switch/gfx/gfx.h>
|
#include <switch/gfx/gfx.h>
|
||||||
#include <switch/gfx/parcel.h>
|
#include <switch/gfx/parcel.h>
|
||||||
#include <switch/gfx/gfxproducer.h>
|
#include <switch/gfx/buffer_producer.h>
|
||||||
#include <switch/gfx/ioctl.h>
|
#include <switch/gfx/ioctl.h>
|
||||||
#include <switch/gfx/nvioctl.h>
|
#include <switch/gfx/nvioctl.h>
|
||||||
#include <switch/gfx/nvgfx.h>
|
#include <switch/gfx/nvgfx.h>
|
||||||
|
11
nx/include/switch/gfx/buffer_producer.h
Normal file
11
nx/include/switch/gfx/buffer_producer.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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 bufferProducerDetachBuffer(s32 slot);
|
||||||
|
Result bufferProducerQueueBuffer(s32 buf, u8 input[0x5c]);
|
||||||
|
Result bufferProducerQuery(s32 what, s32* value);
|
||||||
|
Result bufferProducerConnect(s32 api, bool producerControlledByApp);
|
||||||
|
Result bufferProducerDisconnect(s32 api);
|
||||||
|
Result bufferProducerTegraBufferInit(s32 buf, u8 input[0x178]);
|
@ -1,11 +0,0 @@
|
|||||||
Result gfxproducerInitialize(binderSession *session);
|
|
||||||
void gfxproducerExit();
|
|
||||||
|
|
||||||
Result gfxproducerRequestBuffer(s32 bufferIdx);
|
|
||||||
Result gfxproducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf);
|
|
||||||
Result gfxproducerDetachBuffer(s32 slot);
|
|
||||||
Result gfxproducerQueueBuffer(s32 buf, u8 input[0x5c]);
|
|
||||||
Result gfxproducerQuery(s32 what, s32* value);
|
|
||||||
Result gfxproducerConnect(s32 api, bool producerControlledByApp);
|
|
||||||
Result gfxproducerDisconnect(s32 api);
|
|
||||||
Result gfxproducerTegraBufferInit(s32 buf, u8 input[0x178]);
|
|
@ -9,20 +9,19 @@ typedef struct {
|
|||||||
|
|
||||||
u8 *ParcelObjects;
|
u8 *ParcelObjects;
|
||||||
u32 ParcelObjectsSize;
|
u32 ParcelObjectsSize;
|
||||||
} parcelContext;
|
} Parcel;
|
||||||
|
|
||||||
void parcelInitializeContext(parcelContext *ctx);
|
void parcelInitialize(Parcel *ctx);
|
||||||
Result parcelTransact(binderSession *session, u32 code, parcelContext *in_parcel, parcelContext *reply_parcel);
|
Result parcelTransact(binderSession *session, u32 code, Parcel *in_parcel, Parcel *reply_parcel);
|
||||||
|
|
||||||
void* parcelWriteData(parcelContext *ctx, void* data, size_t data_size);
|
void* parcelWriteData(Parcel *ctx, void* data, size_t data_size);
|
||||||
void* parcelReadData(parcelContext *ctx, void* data, size_t data_size);
|
void* parcelReadData(Parcel *ctx, void* data, size_t data_size);
|
||||||
|
|
||||||
void parcelWriteInt32(parcelContext *ctx, s32 val);
|
void parcelWriteInt32(Parcel *ctx, s32 val);
|
||||||
void parcelWriteUInt32(parcelContext *ctx, u32 val);
|
void parcelWriteUInt32(Parcel *ctx, u32 val);
|
||||||
void parcelWriteString16(parcelContext *ctx, const char *str);
|
void parcelWriteString16(Parcel *ctx, const char *str);
|
||||||
|
void parcelWriteInterfaceToken(Parcel *ctx, const char *interface);
|
||||||
|
|
||||||
void parcelWriteInterfaceToken(parcelContext *ctx, const char *interface);
|
s32 parcelReadInt32(Parcel *ctx);
|
||||||
|
u32 parcelReadUInt32(Parcel *ctx);
|
||||||
s32 parcelReadInt32(parcelContext *ctx);
|
|
||||||
u32 parcelReadUInt32(parcelContext *ctx);
|
|
||||||
|
|
||||||
|
@ -30,4 +30,5 @@
|
|||||||
#define LIBNX_IOERROR 9
|
#define LIBNX_IOERROR 9
|
||||||
#define LIBNX_BADINPUT 10
|
#define LIBNX_BADINPUT 10
|
||||||
#define LIBNX_BADREENT 11
|
#define LIBNX_BADREENT 11
|
||||||
|
#define LIBNX_BUFFERPRODUCER_ERROR 12
|
||||||
#define LIBNX_PARCEL_ERRBASE 100
|
#define LIBNX_PARCEL_ERRBASE 100
|
||||||
|
252
nx/source/gfx/buffer_producer.c
Normal file
252
nx/source/gfx/buffer_producer.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
// This implements the version of Android IGraphicBufferProducer used by Switch.
|
||||||
|
// 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.
|
||||||
|
enum {
|
||||||
|
/* 0x1 */ REQUEST_BUFFER = BINDER_FIRST_CALL_TRANSACTION,
|
||||||
|
/* 0x2 */ SET_BUFFER_COUNT,
|
||||||
|
/* 0x3 */ DEQUEUE_BUFFER,
|
||||||
|
/* 0x4 */ DETACH_BUFFER,
|
||||||
|
/* 0x5 */ DETACH_NEXT_BUFFER,
|
||||||
|
/* 0x6 */ ATTACH_BUFFER,
|
||||||
|
/* 0x7 */ QUEUE_BUFFER,
|
||||||
|
/* 0x8 */ CANCEL_BUFFER,
|
||||||
|
/* 0x9 */ QUERY,
|
||||||
|
/* 0xA */ CONNECT,
|
||||||
|
/* 0xB */ DISCONNECT,
|
||||||
|
/* 0xC */ SET_SIDEBAND_STREAM,
|
||||||
|
/* 0xD */ ALLOCATE_BUFFERS,
|
||||||
|
/* 0xE */ TEGRA_BUFFER_INIT, // Custom Switch-specific command - unofficial name.
|
||||||
|
};
|
||||||
|
|
||||||
|
static char g_bufferProducer_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer";
|
||||||
|
|
||||||
|
static binderSession *g_bufferProducerBinderSession;
|
||||||
|
|
||||||
|
Result bufferProducerInitialize(binderSession *session)
|
||||||
|
{
|
||||||
|
g_bufferProducerBinderSession = session;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferProducerExit()
|
||||||
|
{
|
||||||
|
g_bufferProducerBinderSession = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerRequestBuffer(s32 bufferIdx)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
parcelWriteInt32(&parcel, bufferIdx);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
/*
|
||||||
|
int nonNull = parcelReadInt32(&parcel_reply);
|
||||||
|
|
||||||
|
if (nonNull != 0) {
|
||||||
|
// Fixme
|
||||||
|
fatalSimple(222 | (100 << 9));
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = parcelReadInt32(&parcel_reply);
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
rc = MAKERESULT(MODULE_LIBNX, LIBNX_BUFFERPRODUCER_ERROR);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
|
||||||
|
parcelWriteInt32(&parcel, async);
|
||||||
|
parcelWriteUInt32(&parcel, width);
|
||||||
|
parcelWriteUInt32(&parcel, height);
|
||||||
|
parcelWriteInt32(&parcel, format);
|
||||||
|
parcelWriteUInt32(&parcel, usage);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
// TODO: parse reply
|
||||||
|
*buf = parcelReadInt32(&parcel_reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerDetachBuffer(s32 slot)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
parcelWriteInt32(&parcel, slot);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, DETACH_BUFFER, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
//TODO: parse reply
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerQueueBuffer(s32 buf, u8 input[0x5c])
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
parcelWriteInt32(&parcel, buf);
|
||||||
|
parcelWriteData(&parcel, input, 0x5c);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
//TODO: parse reply
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerQuery(s32 what, s32* value)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
parcelWriteInt32(&parcel, what);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, QUERY, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*value = parcelReadInt32(&parcel_reply);
|
||||||
|
|
||||||
|
int result = parcelReadInt32(&parcel_reply);
|
||||||
|
if (result != 0)
|
||||||
|
rc = MAKERESULT(MODULE_LIBNX, LIBNX_BUFFERPRODUCER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerConnect(s32 api, bool producerControlledByApp)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
|
||||||
|
// Hard-code this as if listener==NULL, since that's not known to be used officially.
|
||||||
|
parcelWriteInt32(&parcel, 0);
|
||||||
|
parcelWriteInt32(&parcel, api);
|
||||||
|
parcelWriteInt32(&parcel, producerControlledByApp);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, CONNECT, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
//TODO: parse reply (contains 32bit width and height)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerDisconnect(s32 api)
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession == NULL)
|
||||||
|
return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
parcelWriteInt32(&parcel, api);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, DISCONNECT, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
//TODO: parse reply
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result bufferProducerTegraBufferInit(s32 buf, u8 input[0x178])
|
||||||
|
{
|
||||||
|
Result rc;
|
||||||
|
Parcel parcel, parcel_reply;
|
||||||
|
|
||||||
|
if (g_bufferProducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
||||||
|
|
||||||
|
parcelInitialize(&parcel);
|
||||||
|
parcelInitialize(&parcel_reply);
|
||||||
|
|
||||||
|
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
|
||||||
|
parcelWriteInt32(&parcel, buf);
|
||||||
|
parcelWriteData(&parcel, input, 0x178);
|
||||||
|
|
||||||
|
rc = parcelTransact(g_bufferProducerBinderSession, TEGRA_BUFFER_INIT, &parcel, &parcel_reply);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
// TODO: parse reply
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ static Result _gfxDequeueBuffer() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gfxproducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer);
|
rc = bufferProducerDequeueBuffer(/*1*/0, 1280, 720, 0, 0x300, &g_gfxCurrentProducerBuffer);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ static Result _gfxQueueBuffer(s32 buf) {
|
|||||||
|
|
||||||
ptr64[1] = svcGetSystemTick();//Unknown what is actually used for timestamp, but shouldn't(?) matter.
|
ptr64[1] = svcGetSystemTick();//Unknown what is actually used for timestamp, but shouldn't(?) matter.
|
||||||
|
|
||||||
rc = gfxproducerQueueBuffer(buf, (u8*)g_gfxQueueBufferData);
|
rc = bufferProducerQueueBuffer(buf, (u8*)g_gfxQueueBufferData);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
/*if(buf==0) {
|
/*if(buf==0) {
|
||||||
@ -121,9 +121,9 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L
|
|||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = nvInitialize(nv_servicetype, nv_transfermem_size);
|
if (R_SUCCEEDED(rc)) rc = nvInitialize(nv_servicetype, nv_transfermem_size);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = gfxproducerInitialize(&g_gfxBinderSession);
|
if (R_SUCCEEDED(rc)) rc = bufferProducerInitialize(&g_gfxBinderSession);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = gfxproducerConnect(2, 0);
|
if (R_SUCCEEDED(rc)) rc = bufferProducerConnect(2, 0);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = 1;
|
if (R_SUCCEEDED(rc)) g_gfx_ProducerConnected = 1;
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L
|
|||||||
rc = _gfxDequeueBuffer();
|
rc = _gfxDequeueBuffer();
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
|
|
||||||
rc = gfxproducerRequestBuffer(g_gfxCurrentProducerBuffer);
|
rc = bufferProducerRequestBuffer(g_gfxCurrentProducerBuffer);
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
|
|
||||||
g_gfx_ProducerSlotsRequested[i] = 1;
|
g_gfx_ProducerSlotsRequested[i] = 1;
|
||||||
@ -162,12 +162,12 @@ static Result _gfxInit(viServiceType servicetype, const char *DisplayName, u32 L
|
|||||||
if (R_FAILED(rc)) {
|
if (R_FAILED(rc)) {
|
||||||
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
||||||
for(i=0; i<2; i++) {
|
for(i=0; i<2; i++) {
|
||||||
if (g_gfx_ProducerSlotsRequested[i]) gfxproducerDetachBuffer(i);
|
if (g_gfx_ProducerSlotsRequested[i]) bufferProducerDetachBuffer(i);
|
||||||
}
|
}
|
||||||
if (g_gfx_ProducerConnected) gfxproducerDisconnect(2);
|
if (g_gfx_ProducerConnected) bufferProducerDisconnect(2);
|
||||||
|
|
||||||
nvgfxExit();
|
nvgfxExit();
|
||||||
gfxproducerExit();
|
bufferProducerExit();
|
||||||
binderExitSession(&g_gfxBinderSession);
|
binderExitSession(&g_gfxBinderSession);
|
||||||
nvExit();
|
nvExit();
|
||||||
|
|
||||||
@ -223,13 +223,13 @@ void gfxExit(void) {
|
|||||||
|
|
||||||
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
|
||||||
for(i=0; i<2; i++) {
|
for(i=0; i<2; i++) {
|
||||||
if (g_gfx_ProducerSlotsRequested[i]) gfxproducerDetachBuffer(i);
|
if (g_gfx_ProducerSlotsRequested[i]) bufferProducerDetachBuffer(i);
|
||||||
}
|
}
|
||||||
if (g_gfx_ProducerConnected) gfxproducerDisconnect(2);
|
if (g_gfx_ProducerConnected) bufferProducerDisconnect(2);
|
||||||
|
|
||||||
nvgfxExit();
|
nvgfxExit();
|
||||||
|
|
||||||
gfxproducerExit();
|
bufferProducerExit();
|
||||||
binderExitSession(&g_gfxBinderSession);
|
binderExitSession(&g_gfxBinderSession);
|
||||||
|
|
||||||
nvExit();
|
nvExit();
|
||||||
|
@ -1,218 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include <switch.h>
|
|
||||||
|
|
||||||
//This implements the version of Android IGraphicBufferProducer used by Switch, 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.
|
|
||||||
enum {
|
|
||||||
REQUEST_BUFFER = BINDER_FIRST_CALL_TRANSACTION, //0x1
|
|
||||||
SET_BUFFER_COUNT, //0x2
|
|
||||||
DEQUEUE_BUFFER, //0x3
|
|
||||||
DETACH_BUFFER, //0x4
|
|
||||||
DETACH_NEXT_BUFFER, //0x5
|
|
||||||
ATTACH_BUFFER, //0x6
|
|
||||||
QUEUE_BUFFER, //0x7
|
|
||||||
CANCEL_BUFFER, //0x8
|
|
||||||
QUERY, //0x9
|
|
||||||
CONNECT, //0xA
|
|
||||||
DISCONNECT, //0xB
|
|
||||||
SET_SIDEBAND_STREAM, //0xC
|
|
||||||
ALLOCATE_BUFFERS, //0xD
|
|
||||||
TEGRA_BUFFER_INIT, //0xE (Custom Switch-specific command - unofficial name)
|
|
||||||
};
|
|
||||||
|
|
||||||
static char g_gfxproducer_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer";
|
|
||||||
|
|
||||||
static binderSession *g_gfxproducerBinderSession;
|
|
||||||
|
|
||||||
Result gfxproducerInitialize(binderSession *session) {
|
|
||||||
g_gfxproducerBinderSession = session;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gfxproducerExit() {
|
|
||||||
g_gfxproducerBinderSession = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerRequestBuffer(s32 bufferIdx) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
parcelWriteInt32(&parcel, bufferIdx);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
|
|
||||||
parcelWriteInt32(&parcel, async);
|
|
||||||
parcelWriteUInt32(&parcel, width);
|
|
||||||
parcelWriteUInt32(&parcel, height);
|
|
||||||
parcelWriteInt32(&parcel, format);
|
|
||||||
parcelWriteUInt32(&parcel, usage);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply
|
|
||||||
|
|
||||||
*buf = parcelReadInt32(&parcel_reply);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerDetachBuffer(s32 slot) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
parcelWriteInt32(&parcel, slot);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, DETACH_BUFFER, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerQueueBuffer(s32 buf, u8 input[0x5c]) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
|
|
||||||
parcelWriteInt32(&parcel, buf);
|
|
||||||
parcelWriteData(&parcel, input, 0x5c);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerQuery(s32 what, s32* value) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
|
|
||||||
parcelWriteInt32(&parcel, what);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, QUERY, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
*value = parcelReadInt32(&parcel_reply);
|
|
||||||
rc = parcelReadInt32(&parcel_reply);
|
|
||||||
if (rc) rc = MAKERESULT(MODULE_LIBNX, LIBNX_PARCEL_ERRBASE);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerConnect(s32 api, bool producerControlledByApp) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
|
|
||||||
//Hard-code this as if listener==NULL, since that's not known to be used officially.
|
|
||||||
parcelWriteInt32(&parcel, 0);
|
|
||||||
|
|
||||||
parcelWriteInt32(&parcel, api);
|
|
||||||
parcelWriteInt32(&parcel, producerControlledByApp);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, CONNECT, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply (contains 32bit width and height)
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerDisconnect(s32 api) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
|
|
||||||
parcelWriteInt32(&parcel, api);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, DISCONNECT, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result gfxproducerTegraBufferInit(s32 buf, u8 input[0x178]) {
|
|
||||||
Result rc;
|
|
||||||
parcelContext parcel, parcel_reply;
|
|
||||||
|
|
||||||
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
|
|
||||||
|
|
||||||
parcelInitializeContext(&parcel);
|
|
||||||
parcelInitializeContext(&parcel_reply);
|
|
||||||
|
|
||||||
parcelWriteInterfaceToken(&parcel, g_gfxproducer_InterfaceDescriptor);
|
|
||||||
|
|
||||||
parcelWriteInt32(&parcel, buf);
|
|
||||||
parcelWriteData(&parcel, input, 0x178);
|
|
||||||
|
|
||||||
rc = parcelTransact(g_gfxproducerBinderSession, TEGRA_BUFFER_INIT, &parcel, &parcel_reply);
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
//TODO: parse reply
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -286,7 +286,7 @@ Result nvgfxInitialize(void) {
|
|||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
|
|
||||||
if(pos==1) {
|
if(pos==1) {
|
||||||
rc = gfxproducerQuery(2, &tmp);//"NATIVE_WINDOW_FORMAT"
|
rc = bufferProducerQuery(2, &tmp);//"NATIVE_WINDOW_FORMAT"
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
|
|
||||||
for(i=0; i<2; i++) {
|
for(i=0; i<2; i++) {
|
||||||
@ -309,7 +309,7 @@ Result nvgfxInitialize(void) {
|
|||||||
g_gfxprod_BufferInitData[0x20] = tmpval;
|
g_gfxprod_BufferInitData[0x20] = tmpval;
|
||||||
g_gfxprod_BufferInitData[0x21] = g_nvgfx_singleframebuf_size*i;
|
g_gfxprod_BufferInitData[0x21] = g_nvgfx_singleframebuf_size*i;
|
||||||
ptr64[0x170>>3] = svcGetSystemTick();
|
ptr64[0x170>>3] = svcGetSystemTick();
|
||||||
rc = gfxproducerTegraBufferInit(i, (u8*)g_gfxprod_BufferInitData);
|
rc = bufferProducerTegraBufferInit(i, (u8*)g_gfxprod_BufferInitData);
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
}
|
}
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
|
@ -10,12 +10,12 @@ u8 parcel_reply_log[0x10000] = {0};
|
|||||||
size_t parcel_reply_log_size = 0;
|
size_t parcel_reply_log_size = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void parcelInitializeContext(parcelContext *ctx) {
|
void parcelInitialize(Parcel *ctx) {
|
||||||
memset(ctx, 0, sizeof(parcelContext));
|
memset(ctx, 0, sizeof(Parcel));
|
||||||
ctx->capacity = sizeof(ctx->payload);
|
ctx->capacity = sizeof(ctx->payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result parcelTransact(binderSession *session, u32 code, parcelContext *in_parcel, parcelContext *parcel_reply) {
|
Result parcelTransact(binderSession *session, u32 code, Parcel *in_parcel, Parcel *parcel_reply) {
|
||||||
Result rc=0;
|
Result rc=0;
|
||||||
u8 inparcel[0x400];
|
u8 inparcel[0x400];
|
||||||
u8 outparcel[0x400];
|
u8 outparcel[0x400];
|
||||||
@ -65,7 +65,7 @@ Result parcelTransact(binderSession *session, u32 code, parcelContext *in_parcel
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* parcelWriteData(parcelContext *ctx, void* data, size_t data_size) {
|
void* parcelWriteData(Parcel *ctx, void* data, size_t data_size) {
|
||||||
void* ptr = &ctx->payload[ctx->size];
|
void* ptr = &ctx->payload[ctx->size];
|
||||||
|
|
||||||
if(data_size & BIT(31))
|
if(data_size & BIT(31))
|
||||||
@ -84,7 +84,7 @@ void* parcelWriteData(parcelContext *ctx, void* data, size_t data_size) {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* parcelReadData(parcelContext *ctx, void* data, size_t data_size) {
|
void* parcelReadData(Parcel *ctx, void* data, size_t data_size) {
|
||||||
void* ptr = ctx->payload;
|
void* ptr = ctx->payload;
|
||||||
|
|
||||||
if(data_size & BIT(31))
|
if(data_size & BIT(31))
|
||||||
@ -103,7 +103,7 @@ void* parcelReadData(parcelContext *ctx, void* data, size_t data_size) {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parcelWriteString16(parcelContext *ctx, const char *str) {
|
void parcelWriteString16(Parcel *ctx, const char *str) {
|
||||||
u32 pos, len;
|
u32 pos, len;
|
||||||
u16 *ptr;
|
u16 *ptr;
|
||||||
|
|
||||||
@ -120,27 +120,27 @@ void parcelWriteString16(parcelContext *ctx, const char *str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 parcelReadInt32(parcelContext *ctx) {
|
s32 parcelReadInt32(Parcel *ctx) {
|
||||||
s32 val = 0;
|
s32 val = 0;
|
||||||
parcelReadData(ctx, &val, sizeof(val));
|
parcelReadData(ctx, &val, sizeof(val));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 parcelReadUInt32(parcelContext *ctx) {
|
u32 parcelReadUInt32(Parcel *ctx) {
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
parcelReadData(ctx, &val, sizeof(val));
|
parcelReadData(ctx, &val, sizeof(val));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parcelWriteInt32(parcelContext *ctx, s32 val) {
|
void parcelWriteInt32(Parcel *ctx, s32 val) {
|
||||||
parcelWriteData(ctx, &val, sizeof(val));
|
parcelWriteData(ctx, &val, sizeof(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
void parcelWriteUInt32(parcelContext *ctx, u32 val) {
|
void parcelWriteUInt32(Parcel *ctx, u32 val) {
|
||||||
parcelWriteData(ctx, &val, sizeof(val));
|
parcelWriteData(ctx, &val, sizeof(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
void parcelWriteInterfaceToken(parcelContext *ctx, const char *interface) {
|
void parcelWriteInterfaceToken(Parcel *ctx, const char *interface) {
|
||||||
parcelWriteInt32(ctx, 0x100);
|
parcelWriteInt32(ctx, 0x100);
|
||||||
parcelWriteString16(ctx, interface);
|
parcelWriteString16(ctx, interface);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user