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

View File

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

View File

@ -27,47 +27,50 @@ enum {
/* 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;
}
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;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
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)) {
int nonNull = parcelReadInt32(&parcel_reply);
if (nonNull != 0) {
size_t tmpsize=0;
size_t tmp_size=0;
void* tmp_ptr;
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize);
if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerGraphicBuffer)) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (buf) memcpy(buf, tmp_ptr, sizeof(bufferProducerGraphicBuffer));
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmp_size);
if (tmp_ptr == NULL || tmp_size != sizeof(BqGraphicBuffer))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (buf)
memcpy(buf, tmp_ptr, sizeof(BqGraphicBuffer));
}
int status = parcelReadInt32(&parcel_reply);
@ -80,18 +83,18 @@ Result bufferProducerRequestBuffer(s32 bufferIdx, bufferProducerGraphicBuffer *b
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;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, async);
parcelWriteUInt32(&parcel, width);
@ -99,18 +102,21 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format
parcelWriteInt32(&parcel, format);
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)) {
*buf = parcelReadInt32(&parcel_reply);
if(parcelReadInt32(&parcel_reply)) {
size_t tmpsize=0;
size_t tmp_size=0;
void* tmp_ptr;
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmpsize);
if (tmp_ptr==NULL || tmpsize!=sizeof(bufferProducerFence)) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (fence) memcpy(fence, tmp_ptr, sizeof(bufferProducerFence));
tmp_ptr = parcelReadFlattenedObject(&parcel_reply, &tmp_size);
if (tmp_ptr == NULL || tmp_size != sizeof(BqFence))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (fence)
memcpy(fence, tmp_ptr, sizeof(BqFence));
}
int result = parcelReadInt32(&parcel_reply);
@ -121,21 +127,21 @@ Result bufferProducerDequeueBuffer(bool async, u32 width, u32 height, s32 format
return rc;
}
Result bufferProducerDetachBuffer(s32 slot)
Result bqDetachBuffer(s32 slot)
{
Result rc;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
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)) {
//TODO: parse reply
@ -144,25 +150,26 @@ Result bufferProducerDetachBuffer(s32 slot)
return rc;
}
Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input, bufferProducerQueueBufferOutput *output)
Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *output)
{
Result rc;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
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 (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);
if (result != 0)
@ -172,21 +179,21 @@ Result bufferProducerQueueBuffer(s32 buf, bufferProducerQueueBufferInput *input,
return rc;
}
Result bufferProducerQuery(s32 what, s32* value)
Result bqQuery(s32 what, s32* value)
{
Result rc;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, what);
rc = parcelTransact(g_bufferProducerBinderSession, QUERY, &parcel, &parcel_reply);
rc = parcelTransact(g_bqBinderSession, QUERY, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) {
*value = parcelReadInt32(&parcel_reply);
@ -199,28 +206,29 @@ Result bufferProducerQuery(s32 what, s32* value)
return rc;
}
Result bufferProducerConnect(s32 api, bool producerControlledByApp, bufferProducerQueueBufferOutput *output)
Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *output)
{
Result rc;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
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.
parcelWriteInt32(&parcel, 0);
parcelWriteInt32(&parcel, api);
parcelWriteInt32(&parcel, producerControlledByApp);
rc = parcelTransact(g_bufferProducerBinderSession, CONNECT, &parcel, &parcel_reply);
rc = parcelTransact(g_bqBinderSession, CONNECT, &parcel, &parcel_reply);
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);
if (result != 0)
@ -230,48 +238,52 @@ Result bufferProducerConnect(s32 api, bool producerControlledByApp, bufferProduc
return rc;
}
Result bufferProducerDisconnect(s32 api)
Result bqDisconnect(s32 api)
{
Result rc;
Parcel parcel, parcel_reply;
if (g_bufferProducerBinderSession == NULL)
if (g_bqBinderSession == NULL)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
parcelInitialize(&parcel);
parcelInitialize(&parcel_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, api);
rc = parcelTransact(g_bufferProducerBinderSession, DISCONNECT, &parcel, &parcel_reply);
rc = parcelTransact(g_bqBinderSession, DISCONNECT, &parcel, &parcel_reply);
if (R_SUCCEEDED(rc)) {
//TODO: parse reply
// TODO: parse reply
}
return rc;
}
Result bufferProducerGraphicBufferInit(s32 buf, bufferProducerGraphicBuffer *input)
Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input)
{
Result rc;
Parcel parcel, parcel_reply;
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_reply);
parcelWriteInterfaceToken(&parcel, g_bufferProducer_InterfaceDescriptor);
parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor);
parcelWriteInt32(&parcel, buf);
if (input!=NULL) flag = 1;
parcelWriteInt32(&parcel, flag);
if (flag) parcelWriteFlattenedObject(&parcel, input, sizeof(bufferProducerGraphicBuffer));
if (input != NULL)
flag = 1;
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)) {
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 u8 *g_gfxFramebuf;
static size_t g_gfxFramebufSize;
static bufferProducerFence g_gfx_DequeueBuffer_fence;
static bufferProducerQueueBufferOutput g_gfx_Connect_QueueBufferOutput;
static bufferProducerQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput;
static BqFence g_gfx_DequeueBuffer_fence;
static BqQueueBufferOutput g_gfx_Connect_QueueBufferOutput;
static BqQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput;
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 bufferProducerQueueBufferInput g_gfxQueueBufferData = {
// TODO: Let the user configure some of this?
static BqQueueBufferInput g_gfxQueueBufferData = {
.timestamp = 0x0,
.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.
@ -78,8 +79,8 @@ static bufferProducerQueueBufferInput g_gfxQueueBufferData = {
}
};
//Some of this struct is based on tegra_dc_ext_flip_windowattr.
static bufferProducerGraphicBuffer g_gfx_BufferInitData = {
// Some of this struct is based on tegra_dc_ext_flip_windowattr.
static BqGraphicBuffer g_gfx_BufferInitData = {
.magic = 0x47424652,//"RFBG"/'GBFR'
.format = 0x1,
.usage = 0xb00,
@ -125,8 +126,8 @@ static Result _gfxGetNativeWindowID(u8 *buf, u64 size, s32 *out_ID) {
static Result _gfxDequeueBuffer(void) {
Result rc=0;
bufferProducerFence *fence = &g_gfx_DequeueBuffer_fence;
bufferProducerFence tmp_fence;
BqFence *fence = &g_gfx_DequeueBuffer_fence;
BqFence tmp_fence;
bool async=0;
if (g_gfxMode == GfxMode_TiledSingle) {
@ -134,9 +135,9 @@ static Result _gfxDequeueBuffer(void) {
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.
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 (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;
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 = 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;
@ -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)) { //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++) {
rc = _gfxDequeueBuffer();
if (R_FAILED(rc)) break;
rc = bufferProducerRequestBuffer(g_gfxCurrentProducerBuffer, NULL);
rc = bqRequestBuffer(g_gfxCurrentProducerBuffer, NULL);
if (R_FAILED(rc)) break;
g_gfx_ProducerSlotsRequested[i] = 1;
@ -284,12 +285,12 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
if (R_FAILED(rc)) {
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
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();
bufferProducerExit();
bqExit();
binderExitSession(&g_gfxBinderSession);
nvExit();
@ -353,13 +354,13 @@ void gfxExit(void)
_gfxQueueBuffer(g_gfxCurrentProducerBuffer);
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();
bufferProducerExit();
bqExit();
binderExitSession(&g_gfxBinderSession);
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.timestamp = svcGetSystemTick();
return bufferProducerGraphicBufferInit(buf, &g_gfx_BufferInitData);
return bqGraphicBufferInit(buf, &g_gfx_BufferInitData);
}
static void _waitevent(Handle *handle) {

View File

@ -269,7 +269,7 @@ Result nvgfxInitialize(void) {
}
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)) {
for(i=0; i<2; i++) {

View File

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