libnx/nx/source/gfx/gfxproducer.c
yellows8 b577367011 Implemented nvioctlNvmap_FromID() and nvioctlNvmap_GetID().
Added PARCEL_LOGGING define in parcel.c.
Fixed the 'code' value used in gfxproducerQueueBuffer().
Moved some gfxproducer init into nvgfx.
Moved some nvgfx event init into nvgfxEventInit().
Updated the code using gfxproducerBufferInit() for setting the nvmap-handles.
Disabled a nvQueryEvent() call which now fails.
Other changes.
The setup framebuf/windowbuf is now displayed.
2017-12-27 18:50:15 -05:00

176 lines
5.0 KiB
C

#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
};
static char _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, _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) {
Result rc;
parcelContext parcel, parcel_reply;
if (g_gfxproducerBinderSession==NULL) return MAKERESULT(MODULE_LIBNX, LIBNX_NOTINITIALIZED);
parcelInitializeContext(&parcel);
parcelInitializeContext(&parcel_reply);
parcelWriteInterfaceToken(&parcel, _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
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, _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, _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, _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;
}
//Unknown what this is.
Result gfxproducerBufferInit(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, _gfxproducer_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf);
parcelWriteData(&parcel, input, 0x178);
rc = parcelTransact(g_gfxproducerBinderSession, 0xE, &parcel, &parcel_reply);
if (R_FAILED(rc)) return rc;
//TODO: parse reply
return 0;
}