Style fixes, use structs for parsing parcels, renamed bufferProducer to bq

This commit is contained in:
plutooo 2018-02-20 06:56:10 +01:00 committed by fincs
parent 772c839c8c
commit 978c3f7f15
6 changed files with 198 additions and 163 deletions

View File

@ -4,32 +4,32 @@
typedef struct { typedef struct {
u32 is_valid; u32 is_valid;
nvioctl_fence nv_fences[4]; nvioctl_fence nv_fences[4];
} PACKED bufferProducerFence; } PACKED BqFence;
typedef struct { typedef struct {
s32 left; s32 left;
s32 top; s32 top;
s32 right; s32 right;
s32 bottom; s32 bottom;
} PACKED bufferProducerRect; } PACKED BqRect;
typedef struct { typedef struct {
s64 timestamp; s64 timestamp;
s32 isAutoTimestamp; s32 isAutoTimestamp;
bufferProducerRect crop; BqRect crop;
s32 scalingMode; s32 scalingMode;
u32 transform;//See the NATIVE_WINDOW_TRANSFORM_* enums. u32 transform; // See the NATIVE_WINDOW_TRANSFORM_* enums.
u32 stickyTransform; u32 stickyTransform;
u32 unk[2]; u32 unk[2];
bufferProducerFence fence; BqFence fence;
} PACKED bufferProducerQueueBufferInput; } PACKED BqQueueBufferInput;
typedef struct { typedef struct {
u32 width; u32 width;
u32 height; u32 height;
u32 transformHint; u32 transformHint;
u32 numPendingBuffers; u32 numPendingBuffers;
} PACKED bufferProducerQueueBufferOutput; } PACKED BqQueueBufferOutput;
typedef struct { typedef struct {
u32 magic; u32 magic;
@ -45,7 +45,7 @@ typedef struct {
u32 numFds; u32 numFds;
u32 numInts; u32 numInts;
struct {//Actual size is numFds*4 + numInts*4. struct { // Actual size is numFds*4 + numInts*4.
u32 unk_x0; u32 unk_x0;
u32 nvmap_handle0; u32 nvmap_handle0;
u32 unk_x8; u32 unk_x8;
@ -74,12 +74,12 @@ typedef struct {
u32 unk_x64; u32 unk_x64;
u32 unk_x68; u32 unk_x68;
u32 buffer_size1; u32 buffer_size1;
u32 unk_x70[0x33];//Normally all-zero. u32 unk_x70[0x33]; // Normally all-zero.
u64 timestamp; u64 timestamp;
} PACKED data; } PACKED data;
} PACKED bufferProducerGraphicBuffer; } PACKED BqGraphicBuffer;
//From Android window.h. // From Android window.h.
/* attributes queriable with query() */ /* attributes queriable with query() */
enum { enum {
NATIVE_WINDOW_WIDTH = 0, NATIVE_WINDOW_WIDTH = 0,
@ -90,7 +90,7 @@ enum {
// NATIVE_WINDOW_DEFAULT_HEIGHT = 7, // NATIVE_WINDOW_DEFAULT_HEIGHT = 7,
}; };
//From Android window.h. // From Android window.h.
/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */ /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
enum { enum {
//... //...
@ -100,7 +100,7 @@ enum {
//... //...
}; };
//From Android hardware.h. // From Android hardware.h.
/** /**
* Transformation definitions * Transformation definitions
@ -123,7 +123,7 @@ enum {
HAL_TRANSFORM_ROT_270 = 0x07, HAL_TRANSFORM_ROT_270 = 0x07,
}; };
//From Android window.h. // From Android window.h.
/* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */ /* parameter for NATIVE_WINDOW_SET_BUFFERS_TRANSFORM */
enum { enum {
/* flip source image horizontally */ /* flip source image horizontally */
@ -138,14 +138,14 @@ enum {
NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270, NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
}; };
Result bufferProducerInitialize(Binder *session); Result bqInitialize(Binder *session);
void bufferProducerExit(void); void bqExit(void);
Result bufferProducerRequestBuffer(s32 bufferIdx, bufferProducerGraphicBuffer *buf); Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf);
Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, bufferProducerFence *fence); Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, BqFence *fence);
Result bufferProducerDetachBuffer(s32 slot); Result bqDetachBuffer(s32 slot);
Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input, bufferProducerQueueBufferOutput *output); Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output);
Result bufferProducerQuery(s32 what, s32* value); Result bqQuery(s32 what, s32* value);
Result bufferProducerConnect(s32 api, bool producerControlledByApp, bufferProducerQueueBufferOutput *output); Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output);
Result bufferProducerDisconnect(s32 api); Result bqDisconnect(s32 api);
Result bufferProducerGraphicBufferInit(s32 buf, bufferProducerGraphicBuffer *input); Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input);

View File

@ -2,14 +2,16 @@
#include "../result.h" #include "../result.h"
#include "../gfx/binder.h" #include "../gfx/binder.h"
typedef struct { #define PARCEL_MAX_PAYLOAD 0x400
u8 payload[0x400];
u32 capacity;
u32 size;
u32 pos;
u8 *ParcelObjects; typedef struct {
u32 ParcelObjectsSize; u8 payload[PARCEL_MAX_PAYLOAD];
u32 payload_size;
u8* objects;
u32 objects_size;
u32 capacity;
u32 pos;
} Parcel; } Parcel;
void parcelInitialize(Parcel *ctx); void parcelInitialize(Parcel *ctx);

View File

@ -27,47 +27,50 @@ enum {
/* 0xE */ GRAPHIC_BUFFER_INIT, // Custom Switch-specific command - unofficial name. /* 0xE */ GRAPHIC_BUFFER_INIT, // Custom Switch-specific command - unofficial name.
}; };
static char g_bufferProducer_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer"; static char g_bq_InterfaceDescriptor[] = "android.gui.IGraphicBufferProducer";
static Binder *g_bufferProducerBinderSession; static Binder *g_bqBinderSession;
Result bufferProducerInitialize(Binder *session) Result bqInitialize(Binder *session)
{ {
g_bufferProducerBinderSession = session; g_bqBinderSession = session;
return 0; return 0;
} }
void bufferProducerExit(void) void bqExit(void)
{ {
g_bufferProducerBinderSession = NULL; g_bqBinderSession = NULL;
} }
Result bufferProducerRequestBuffer(s32 bufferIdx, bufferProducerGraphicBuffer *buf) Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, bufferIdx); parcelWriteInt32(&parcel, bufferIdx);
rc = parcelTransact(g_bufferProducerBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, REQUEST_BUFFER, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
int nonNull = parcelReadInt32(&parcel_reply); int nonNull = parcelReadInt32(&parcel_reply);
if (nonNull != 0) { if (nonNull != 0) {
size_t tmpsize=0; size_t tmp_size=0;
void* tmp_ptr; void* tmp_ptr;
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize); tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmp_size);
if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerGraphicBuffer)) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (tmp_ptr == NULL || tmp_size != sizeof(BqGraphicBuffer))
if (buf) memcpy(buf, tmp_ptr, sizeof(bufferProducerGraphicBuffer)); return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (buf)
memcpy(buf, tmp_ptr, sizeof(BqGraphicBuffer));
} }
int status = parcelReadInt32(&parcel_reply); int status = parcelReadInt32(&parcel_reply);
@ -80,18 +83,18 @@ Result bufferProducerRequestBuffer(s32 bufferIdx, bufferProducerGraphicBuffer *b
return rc; return rc;
} }
Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, bufferProducerFence *fence) Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, s32 *buf, BqFence *fence)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, async); parcelWriteInt32(&parcel, async);
parcelWriteUInt32(&parcel, width); parcelWriteUInt32(&parcel, width);
@ -99,18 +102,21 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format
parcelWriteInt32(&parcel, format); parcelWriteInt32(&parcel, format);
parcelWriteUInt32(&parcel, usage); parcelWriteUInt32(&parcel, usage);
rc = parcelTransact(g_bufferProducerBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, DEQUEUE_BUFFER, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
*buf = parcelReadInt32(&parcel_reply); *buf = parcelReadInt32(&parcel_reply);
if(parcelReadInt32(&parcel_reply)) { if(parcelReadInt32(&parcel_reply)) {
size_t tmpsize=0; size_t tmp_size=0;
void* tmp_ptr; void* tmp_ptr;
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize); tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmp_size);
if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerFence)) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (tmp_ptr == NULL || tmp_size != sizeof(BqFence))
if (fence) memcpy(fence, tmp_ptr, sizeof(bufferProducerFence)); return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (fence)
memcpy(fence, tmp_ptr, sizeof(BqFence));
} }
int result = parcelReadInt32(&parcel_reply); int result = parcelReadInt32(&parcel_reply);
@ -121,21 +127,21 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format
return rc; return rc;
} }
Result bufferProducerDetachBuffer(s32 slot) Result bqDetachBuffer(s32 slot)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, slot); parcelWriteInt32(&parcel, slot);
rc = parcelTransact(g_bufferProducerBinderSession, DETACH_BUFFER, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, DETACH_BUFFER, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
//TODO: parse reply //TODO: parse reply
@ -144,25 +150,26 @@ Result bufferProducerDetachBuffer(s32 slot)
return rc; return rc;
} }
Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input, bufferProducerQueueBufferOutput *output) Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf); parcelWriteInt32(&parcel, buf);
parcelWriteFlattenedObject(&parcel, input, sizeof(bufferProducerQueueBufferInput)); parcelWriteFlattenedObject(&parcel, input, sizeof(*input));
rc = parcelTransact(g_bufferProducerBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, QUEUE_BUFFER, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
if (parcelReadData(&parcel_reply, output, sizeof(bufferProducerQueueBufferOutput))==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (parcelReadData(&parcel_reply, output, sizeof(*output)) == NULL)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
int result = parcelReadInt32(&parcel_reply); int result = parcelReadInt32(&parcel_reply);
if (result != 0) if (result != 0)
@ -172,21 +179,21 @@ Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input,
return rc; return rc;
} }
Result bufferProducerQuery(s32 what, s32* value) Result bqQuery(s32 what, s32* value)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, what); parcelWriteInt32(&parcel, what);
rc = parcelTransact(g_bufferProducerBinderSession, QUERY, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, QUERY, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
*value = parcelReadInt32(&parcel_reply); *value = parcelReadInt32(&parcel_reply);
@ -199,28 +206,29 @@ Result bufferProducerQuery(s32 what, s32* value)
return rc; return rc;
} }
Result bufferProducerConnect(s32 api, bool producerControlledByApp, bufferProducerQueueBufferOutput *output) Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
// Hard-code this as if listener==NULL, since that's not known to be used officially. // Hard-code this as if listener==NULL, since that's not known to be used officially.
parcelWriteInt32(&parcel, 0); parcelWriteInt32(&parcel, 0);
parcelWriteInt32(&parcel, api); parcelWriteInt32(&parcel, api);
parcelWriteInt32(&parcel, producerControlledByApp); parcelWriteInt32(&parcel, producerControlledByApp);
rc = parcelTransact(g_bufferProducerBinderSession, CONNECT, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, CONNECT, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
if (parcelReadData(&parcel_reply, output, sizeof(bufferProducerQueueBufferOutput))==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (parcelReadData(&parcel_reply, output, sizeof(*output)) == NULL)
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
int result = parcelReadInt32(&parcel_reply); int result = parcelReadInt32(&parcel_reply);
if (result != 0) if (result != 0)
@ -230,48 +238,52 @@ Result bufferProducerConnect(s32 api, bool producerControlledByApp, bufferProduc
return rc; return rc;
} }
Result bufferProducerDisconnect(s32 api) Result bqDisconnect(s32 api)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL) if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, api); parcelWriteInt32(&parcel, api);
rc = parcelTransact(g_bufferProducerBinderSession, DISCONNECT, &parcel, &parcel_reply); rc = parcelTransact(g_bqBinderSession, DISCONNECT, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
//TODO: parse reply // TODO: parse reply
} }
return rc; return rc;
} }
Result bufferProducerGraphicBufferInit(s32 buf, bufferProducerGraphicBuffer *input) Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input)
{ {
Result rc; Result rc;
Parcel parcel, parcel_reply; Parcel parcel, parcel_reply;
bool flag = 0; bool flag = 0;
if (g_bufferProducerBinderSession==NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel); parcelInitialize(&parcel);
parcelInitialize(&parcel_reply); parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf); parcelWriteInt32(&parcel, buf);
if (input!=NULL) flag = 1; if (input != NULL)
parcelWriteInt32(&parcel, flag); flag = 1;
if (flag) parcelWriteFlattenedObject(&parcel, input, sizeof(bufferProducerGraphicBuffer));
rc = parcelTransact(g_bufferProducerBinderSession, GRAPHIC_BUFFER_INIT, &parcel, &parcel_reply); parcelWriteInt32(&parcel, flag);
if (flag)
parcelWriteFlattenedObject(&parcel, input, sizeof(BqGraphicBuffer));
rc = parcelTransact(g_bqBinderSession, GRAPHIC_BUFFER_INIT, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
int result = parcelReadInt32(&parcel_reply); int result = parcelReadInt32(&parcel_reply);

View File

@ -26,9 +26,9 @@ static bool g_gfx_ProducerConnected = 0;
static bool g_gfx_ProducerSlotsRequested[2] = {0, 0}; static bool g_gfx_ProducerSlotsRequested[2] = {0, 0};
static u8 *g_gfxFramebuf; static u8 *g_gfxFramebuf;
static size_t g_gfxFramebufSize; static size_t g_gfxFramebufSize;
static bufferProducerFence g_gfx_DequeueBuffer_fence; static BqFence g_gfx_DequeueBuffer_fence;
static bufferProducerQueueBufferOutput g_gfx_Connect_QueueBufferOutput; static BqQueueBufferOutput g_gfx_Connect_QueueBufferOutput;
static bufferProducerQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput; static BqQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput;
static GfxMode g_gfxMode = GfxMode_LinearDouble; static GfxMode g_gfxMode = GfxMode_LinearDouble;
@ -57,7 +57,8 @@ extern nvioctl_fence g_nvgfx_nvhostgpu_gpfifo_fence;
//static Result _gfxGetDisplayResolution(u64 *width, u64 *height); //static Result _gfxGetDisplayResolution(u64 *width, u64 *height);
static bufferProducerQueueBufferInput g_gfxQueueBufferData = { // TODO: Let the user configure some of this?
static BqQueueBufferInput g_gfxQueueBufferData = {
.timestamp = 0x0, .timestamp = 0x0,
.isAutoTimestamp = 0x1, .isAutoTimestamp = 0x1,
.crop = {0x0, 0x0, 0x0, 0x0}, //Official apps which use multiple resolutions configure this for the currently used resolution, depending on the current appletOperationMode. .crop = {0x0, 0x0, 0x0, 0x0}, //Official apps which use multiple resolutions configure this for the currently used resolution, depending on the current appletOperationMode.
@ -78,8 +79,8 @@ static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
} }
}; };
//Some of this struct is based on tegra_dc_ext_flip_windowattr. // Some of this struct is based on tegra_dc_ext_flip_windowattr.
static bufferProducerGraphicBuffer g_gfx_BufferInitData = { static BqGraphicBuffer g_gfx_BufferInitData = {
.magic = 0x47424652,//"RFBG"/'GBFR' .magic = 0x47424652,//"RFBG"/'GBFR'
.format = 0x1, .format = 0x1,
.usage = 0xb00, .usage = 0xb00,
@ -125,8 +126,8 @@ static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) {
static Result _gfxDequeueBuffer(void) { static Result _gfxDequeueBuffer(void) {
Result rc=0; Result rc=0;
bufferProducerFence *fence = &g_gfx_DequeueBuffer_fence; BqFence *fence = &g_gfx_DequeueBuffer_fence;
bufferProducerFence tmp_fence; BqFence tmp_fence;
bool async=0; bool async=0;
if (g_gfxMode == GfxMode_TiledSingle) { if (g_gfxMode == GfxMode_TiledSingle) {
@ -134,9 +135,9 @@ static Result _gfxDequeueBuffer(void) {
return 0; return 0;
} }
memcpy(&tmp_fence, fence, sizeof(bufferProducerFence));//Offical sw waits on the fence from the previous DequeueBuffer call. Using the fence from the current DequeueBuffer call results in nvgfxEventWait() failing. 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.
rc = bufferProducerDequeueBuffer(async, g_gfx_framebuf_width, g_gfx_framebuf_height, 0, 0x300, &g_gfxCurrentProducerBuffer, fence); 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. //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) && 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);
@ -158,7 +159,7 @@ static Result _gfxQueueBuffer(s32 buf) {
//if (g_nvgfx_nvhostgpu_gpfifo_fence.id) rc = nvgfxEventWait(g_nvgfx_nvhostgpu_gpfifo_fence.id, g_nvgfx_nvhostgpu_gpfifo_fence.value, -1); //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; if (R_FAILED(rc)) return rc;
rc = bufferProducerQueueBuffer(buf, &g_gfxQueueBufferData, &g_gfx_QueueBuffer_QueueBufferOutput); rc = bqQueueBuffer(buf, &g_gfxQueueBufferData, &g_gfx_QueueBuffer_QueueBufferOutput);
if (R_FAILED(rc)) return rc; if (R_FAILED(rc)) return rc;
return rc; return rc;
@ -240,9 +241,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 = bufferProducerInitialize(&g_gfxBinderSession); if (R_SUCCEEDED(rc)) rc = bqInitialize(&g_gfxBinderSession);
if (R_SUCCEEDED(rc)) rc = bufferProducerConnect(NATIVE_WINDOW_API_CPU, 0, &g_gfx_Connect_QueueBufferOutput); 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)) g_gfx_ProducerConnected = 1;
@ -250,12 +251,12 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
if (R_SUCCEEDED(rc)) rc = nvgfxGetFramebuffer(&g_gfxFramebuf, &g_gfxFramebufSize); if (R_SUCCEEDED(rc)) rc = nvgfxGetFramebuffer(&g_gfxFramebuf, &g_gfxFramebufSize);
if (R_SUCCEEDED(rc)) { //Official sw would use bufferProducerRequestBuffer() when required during swap-buffers/or similar, but that's not really an option here due to gfxSetDoubleBuffering(). 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++) { for(i=0; i<2; i++) {
rc = _gfxDequeueBuffer(); rc = _gfxDequeueBuffer();
if (R_FAILED(rc)) break; if (R_FAILED(rc)) break;
rc = bufferProducerRequestBuffer(g_gfxCurrentProducerBuffer, NULL); rc = bqRequestBuffer(g_gfxCurrentProducerBuffer, NULL);
if (R_FAILED(rc)) break; if (R_FAILED(rc)) break;
g_gfx_ProducerSlotsRequested[i] = 1; g_gfx_ProducerSlotsRequested[i] = 1;
@ -284,12 +285,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]) bufferProducerDetachBuffer(i); if (g_gfx_ProducerSlotsRequested[i]) bqDetachBuffer(i);
} }
if (g_gfx_ProducerConnected) bufferProducerDisconnect(NATIVE_WINDOW_API_CPU); if (g_gfx_ProducerConnected) bqDisconnect(NATIVE_WINDOW_API_CPU);
nvgfxExit(); nvgfxExit();
bufferProducerExit(); bqExit();
binderExitSession(&g_gfxBinderSession); binderExitSession(&g_gfxBinderSession);
nvExit(); nvExit();
@ -353,13 +354,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]) bufferProducerDetachBuffer(i); if (g_gfx_ProducerSlotsRequested[i]) bqDetachBuffer(i);
} }
if (g_gfx_ProducerConnected) bufferProducerDisconnect(2); if (g_gfx_ProducerConnected) bqDisconnect(2);
nvgfxExit(); nvgfxExit();
bufferProducerExit(); bqExit();
binderExitSession(&g_gfxBinderSession); binderExitSession(&g_gfxBinderSession);
nvExit(); nvExit();
@ -482,7 +483,7 @@ Result _gfxGraphicBufferInit(s32 buf, u32 nvmap_handle) {
g_gfx_BufferInitData.data.buffer_offset = g_gfx_singleframebuf_size*buf; g_gfx_BufferInitData.data.buffer_offset = g_gfx_singleframebuf_size*buf;
g_gfx_BufferInitData.data.timestamp = svcGetSystemTick(); g_gfx_BufferInitData.data.timestamp = svcGetSystemTick();
return bufferProducerGraphicBufferInit(buf, &g_gfx_BufferInitData); return bqGraphicBufferInit(buf, &g_gfx_BufferInitData);
} }
static void _waitevent(Handle *handle) { static void _waitevent(Handle *handle) {

View File

@ -269,7 +269,7 @@ Result nvgfxInitialize(void) {
} }
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
rc = bufferProducerQuery(NATIVE_WINDOW_FORMAT, &tmp);//TODO: What does official sw use the output from this for? rc = bqQuery(NATIVE_WINDOW_FORMAT, &tmp);//TODO: What does official sw use the output from this for?
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
for(i=0; i<2; i++) { for(i=0; i<2; i++) {

View File

@ -2,14 +2,14 @@
#include "result.h" #include "result.h"
#include "gfx/parcel.h" #include "gfx/parcel.h"
//This implements Android Parcel, hence names etc here are based on Android Parcel.cpp. // This implements Android Parcel, hence names etc here are based on Android Parcel.cpp.
//#define PARCEL_LOGGING typedef struct {
u32 payload_size;
#ifdef PARCEL_LOGGING u32 payload_off;
u8 parcel_reply_log[0x10000] = {0}; u32 objects_size;
size_t parcel_reply_log_size = 0; u32 objects_off;
#endif } ParcelHeader;
void parcelInitialize(Parcel *ctx) void parcelInitialize(Parcel *ctx)
{ {
@ -17,68 +17,86 @@ void parcelInitialize(Parcel *ctx)
ctx->capacity = sizeof(ctx->payload); ctx->capacity = sizeof(ctx->payload);
} }
Result parcelTransact(Binder *session, u32 code, Parcel *in_parcel, Parcel *parcel_reply) Result parcelTransact(Binder *session, u32 code, Parcel *in_parcel, Parcel *out_parcel)
{ {
Result rc=0; Result rc;
u8 inparcel[0x400]; char in[PARCEL_MAX_PAYLOAD];
u8 outparcel[0x400]; char out[PARCEL_MAX_PAYLOAD];
size_t outparcel_size = sizeof(outparcel);
u32 *inparcel32 = (u32*)inparcel;
u32 *outparcel32 = (u32*)outparcel;
u32 payloadSize = in_parcel->size;
u32 ParcelObjectsSize = in_parcel->ParcelObjectsSize;
memset(inparcel, 0, sizeof(inparcel)); memset(in, 0, sizeof(in));
memset(outparcel, 0, outparcel_size); memset(out, 0, sizeof(out));
if((size_t)payloadSize >= sizeof(inparcel) || (size_t)ParcelObjectsSize >= sizeof(inparcel) || ((size_t)payloadSize)+((size_t)ParcelObjectsSize)+0x10 >= sizeof(inparcel)) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (in_parcel->payload_size > sizeof(in))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (in_parcel->objects_size > sizeof(in))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
inparcel32[0] = payloadSize;//payloadSize size_t total_size = 0;
inparcel32[1] = 0x10;//payloadOffset total_size += sizeof(ParcelHeader);
inparcel32[2] = ParcelObjectsSize;//ParcelObjectsSize total_size += in_parcel->payload_size;
inparcel32[3] = 0x10+payloadSize;//ParcelObjectsOffset total_size += in_parcel->objects_size;
if(in_parcel->payload && payloadSize)memcpy(&inparcel[inparcel32[1]], in_parcel->payload, payloadSize); if (total_size > sizeof(in))
if(in_parcel->ParcelObjects && ParcelObjectsSize)memcpy(&inparcel[inparcel32[3]], in_parcel->ParcelObjects, ParcelObjectsSize); return MAKERESULT(Module_Libnx, LibnxError_BadInput);
rc = binderTransactParcel(session, code, inparcel, payloadSize+ParcelObjectsSize+0x10, outparcel, outparcel_size, 0); ParcelHeader* in_hdr = (ParcelHeader*) &in;
if (R_FAILED(rc)) return rc; in_hdr->payload_size = in_parcel->payload_size;
in_hdr->payload_off = sizeof(ParcelHeader);
in_hdr->objects_size = in_parcel->objects_size;
in_hdr->objects_off = sizeof(ParcelHeader) + in_parcel->payload_size;
if((size_t)outparcel32[1] >= outparcel_size || ((size_t)outparcel32[0])+((size_t)outparcel32[1]) >= outparcel_size) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (in_parcel->payload != NULL)
if((size_t)outparcel32[2] >= outparcel_size || ((size_t)outparcel32[2])+((size_t)outparcel32[3]) >= outparcel_size) return MAKERESULT(Module_Libnx, LibnxError_BadInput); memcpy(&in[in_hdr->payload_off], in_parcel->payload, in_parcel->payload_size);
if((size_t)outparcel32[0] >= outparcel_size || (size_t)outparcel32[3] >= outparcel_size) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
memcpy(parcel_reply->payload, &outparcel[outparcel32[1]], outparcel32[0]); if (in_parcel->objects != NULL)
parcel_reply->size = outparcel32[0]; memcpy(&in[in_hdr->objects_off], in_parcel->objects, in_parcel->objects_size);
#ifdef PARCEL_LOGGING rc = binderTransactParcel(session, code, in, total_size, out, sizeof(out), 0);
if(parcel_reply_log_size + sizeof(inparcel) + outparcel_size <= sizeof(parcel_reply_log)) {
memcpy(&parcel_reply_log[parcel_reply_log_size], inparcel, sizeof(inparcel)); if (R_SUCCEEDED(rc))
parcel_reply_log_size+= sizeof(inparcel); {
memcpy(&parcel_reply_log[parcel_reply_log_size], outparcel, outparcel_size); ParcelHeader* out_hdr = (ParcelHeader*) &out;
parcel_reply_log_size+= outparcel_size;
if (out_hdr->payload_size > sizeof(out))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (out_hdr->objects_size > sizeof(out))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (out_hdr->payload_off > sizeof(out))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (out_hdr->objects_off > sizeof(out))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if ((out_hdr->payload_off+out_hdr->payload_size) > sizeof(out))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if ((out_hdr->objects_off+out_hdr->objects_size) > sizeof(out))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
memcpy(out_parcel->payload, &out[out_hdr->payload_off], out_hdr->payload_size);
out_parcel->payload_size = out_hdr->payload_size;
// TODO: Objects are not populated on response.
out_parcel->objects = NULL;
out_parcel->objects_size = 0;
} }
#endif
return 0; return rc;
} }
void* parcelWriteData(Parcel *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->payload_size];
if(data_size & BIT(31)) if (data_size & BIT(31))
return NULL; return NULL;
data_size = (data_size+3) & ~3; data_size = (data_size+3) & ~3;
if(ctx->size + data_size >= ctx->capacity) if (ctx->payload_size + data_size >= ctx->capacity)
return NULL; return NULL;
if(data) if (data)
memcpy(ptr, data, data_size); memcpy(ptr, data, data_size);
ctx->size += data_size; ctx->payload_size += data_size;
return ptr; return ptr;
} }
@ -87,15 +105,15 @@ void* parcelReadData(Parcel *ctx, void* data, size_t data_size)
void* ptr = &ctx->payload[ctx->pos]; void* ptr = &ctx->payload[ctx->pos];
size_t aligned_data_size; size_t aligned_data_size;
if(data_size & BIT(31)) if (data_size & BIT(31))
return NULL; return NULL;
aligned_data_size = (data_size+3) & ~3; aligned_data_size = (data_size+3) & ~3;
if(ctx->pos + aligned_data_size >= ctx->size) if (ctx->pos + aligned_data_size >= ctx->payload_size)
return NULL; return NULL;
if(data) if (data)
memcpy(data, ptr, data_size); memcpy(data, ptr, data_size);
ctx->pos += aligned_data_size; ctx->pos += aligned_data_size;
@ -110,8 +128,7 @@ void parcelWriteUInt32(Parcel *ctx, u32 val) {
parcelWriteData(ctx, &val, sizeof(val)); parcelWriteData(ctx, &val, sizeof(val));
} }
void parcelWriteString16(Parcel *ctx, const char *str) void parcelWriteString16(Parcel *ctx, const char *str) {
{
u32 pos, len; u32 pos, len;
u16 *ptr; u16 *ptr;
@ -120,9 +137,10 @@ void parcelWriteString16(Parcel *ctx, const char *str)
len++; len++;
ptr = parcelWriteData(ctx, NULL, len*2); ptr = parcelWriteData(ctx, NULL, len*2);
if(ptr==NULL)return; if (ptr == NULL)
return;
for(pos=0; pos<len; pos++) { for (pos=0; pos<len; pos++) {
ptr[pos] = (u16)str[pos]; ptr[pos] = (u16)str[pos];
} }
} }
@ -148,16 +166,18 @@ void* parcelReadFlattenedObject(Parcel *ctx, size_t *size) {
s32 len = parcelReadInt32(ctx); s32 len = parcelReadInt32(ctx);
s32 fd_count = parcelReadInt32(ctx); s32 fd_count = parcelReadInt32(ctx);
if (size) *size = (u32)len; if (size)
*size = (u32)len;
if(fd_count!=0)return NULL;//Not going to support fds. if (fd_count != 0)
return NULL; // Not going to support fds.
return parcelReadData(ctx, NULL, len); return parcelReadData(ctx, NULL, len);
} }
void* parcelWriteFlattenedObject(Parcel *ctx, void* data, size_t size) { void* parcelWriteFlattenedObject(Parcel *ctx, void* data, size_t size) {
parcelWriteInt32(ctx, size);//len parcelWriteInt32(ctx, size); // len
parcelWriteInt32(ctx, 0);//fd_count parcelWriteInt32(ctx, 0); // fd_count
return parcelWriteData(ctx, data, size); return parcelWriteData(ctx, data, size);
} }