[client] added initial framework for dma buffer support

This commit is contained in:
Geoffrey McRae 2020-10-29 22:57:04 +11:00
parent 5522e93fb9
commit 0bf73d862d
4 changed files with 87 additions and 7 deletions

View File

@ -51,6 +51,12 @@ typedef struct LG_RendererParams
} }
LG_RendererParams; LG_RendererParams;
typedef enum LG_RendererSupport
{
LG_SUPPORTS_DMABUF
}
LG_RendererSupport;
typedef struct LG_RendererFormat typedef struct LG_RendererFormat
{ {
FrameType type; // frame type FrameType type; // frame type
@ -89,12 +95,13 @@ typedef void (* LG_RendererSetup)();
typedef bool (* LG_RendererCreate )(void ** opaque, const LG_RendererParams params); typedef bool (* LG_RendererCreate )(void ** opaque, const LG_RendererParams params);
typedef bool (* LG_RendererInitialize )(void * opaque, Uint32 * sdlFlags); typedef bool (* LG_RendererInitialize )(void * opaque, Uint32 * sdlFlags);
typedef void (* LG_RendererDeInitialize )(void * opaque); typedef void (* LG_RendererDeInitialize )(void * opaque);
typedef bool (* LG_RendererSupports )(void * opaque, LG_RendererSupport support);
typedef void (* LG_RendererOnRestart )(void * opaque); typedef void (* LG_RendererOnRestart )(void * opaque);
typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect); typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect);
typedef bool (* LG_RendererOnMouseShape )(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data); typedef bool (* LG_RendererOnMouseShape )(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data);
typedef bool (* LG_RendererOnMouseEvent )(void * opaque, const bool visible , const int x, const int y); typedef bool (* LG_RendererOnMouseEvent )(void * opaque, const bool visible , const int x, const int y);
typedef bool (* LG_RendererOnFrameFormat)(void * opaque, const LG_RendererFormat format); typedef bool (* LG_RendererOnFrameFormat)(void * opaque, const LG_RendererFormat format);
typedef bool (* LG_RendererOnFrame )(void * opaque, const FrameBuffer * frame); typedef bool (* LG_RendererOnFrame )(void * opaque, const FrameBuffer * frame, int dmaFD);
typedef void (* LG_RendererOnAlert )(void * opaque, const LG_MsgAlert alert, const char * message, bool ** closeFlag); typedef void (* LG_RendererOnAlert )(void * opaque, const LG_MsgAlert alert, const char * message, bool ** closeFlag);
typedef bool (* LG_RendererRender )(void * opaque, SDL_Window *window); typedef bool (* LG_RendererRender )(void * opaque, SDL_Window *window);
typedef void (* LG_RendererUpdateFPS )(void * opaque, const float avgUPS, const float avgFPS); typedef void (* LG_RendererUpdateFPS )(void * opaque, const float avgUPS, const float avgFPS);
@ -107,6 +114,7 @@ typedef struct LG_Renderer
LG_RendererCreate create; LG_RendererCreate create;
LG_RendererInitialize initialize; LG_RendererInitialize initialize;
LG_RendererDeInitialize deinitialize; LG_RendererDeInitialize deinitialize;
LG_RendererSupports supports;
LG_RendererOnRestart on_restart; LG_RendererOnRestart on_restart;
LG_RendererOnResize on_resize; LG_RendererOnResize on_resize;
LG_RendererOnMouseShape on_mouse_shape; LG_RendererOnMouseShape on_mouse_shape;

View File

@ -338,7 +338,7 @@ bool egl_on_frame_format(void * opaque, const LG_RendererFormat format)
return egl_desktop_setup(this->desktop, format); return egl_desktop_setup(this->desktop, format);
} }
bool egl_on_frame(void * opaque, const FrameBuffer * frame) bool egl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd)
{ {
struct Inst * this = (struct Inst *)opaque; struct Inst * this = (struct Inst *)opaque;

View File

@ -386,7 +386,7 @@ bool opengl_on_frame_format(void * opaque, const LG_RendererFormat format)
return true; return true;
} }
bool opengl_on_frame(void * opaque, const FrameBuffer * frame) bool opengl_on_frame(void * opaque, const FrameBuffer * frame, int dmaFd)
{ {
struct Inst * this = (struct Inst *)opaque; struct Inst * this = (struct Inst *)opaque;

View File

@ -358,13 +358,29 @@ static int cursorThread(void * unused)
static int frameThread(void * unused) static int frameThread(void * unused)
{ {
struct DMAFrameInfo
{
KVMFRFrame * frame;
size_t dataSize;
int fd;
};
LGMP_STATUS status; LGMP_STATUS status;
PLGMPClientQueue queue; PLGMPClientQueue queue;
uint32_t formatVer = 0; uint32_t formatVer = 0;
bool formatValid = false; bool formatValid = false;
size_t dataSize;
LG_RendererFormat lgrFormat; LG_RendererFormat lgrFormat;
//FIXME: Should use LGMP_Q_FRAME_LEN
struct DMAFrameInfo dmaInfo[2] = {0};
const bool useDMA = ivshmemHasDMA(&state.shm) && state.lgr->supports &&
state.lgr->supports(state.lgrData, LG_SUPPORTS_DMABUF);
if (useDMA)
DEBUG_INFO("Using DMA buffer support");
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
lgWaitEvent(e_startup, TIMEOUT_INFINITE); lgWaitEvent(e_startup, TIMEOUT_INFINITE);
if (state.state != APP_STATE_RUNNING) if (state.state != APP_STATE_RUNNING)
@ -409,7 +425,8 @@ static int frameThread(void * unused)
break; break;
} }
KVMFRFrame * frame = (KVMFRFrame *)msg.mem; KVMFRFrame * frame = (KVMFRFrame *)msg.mem;
struct DMAFrameInfo *dma = NULL;
if (!formatValid || frame->formatVer != formatVer) if (!formatValid || frame->formatVer != formatVer)
{ {
@ -420,8 +437,7 @@ static int frameThread(void * unused)
lgrFormat.stride = frame->stride; lgrFormat.stride = frame->stride;
lgrFormat.pitch = frame->pitch; lgrFormat.pitch = frame->pitch;
size_t dataSize; bool error = false;
bool error = false;
switch(frame->type) switch(frame->type)
{ {
case FRAME_TYPE_RGBA: case FRAME_TYPE_RGBA:
@ -471,6 +487,54 @@ static int frameThread(void * unused)
} }
} }
if (useDMA)
{
/* find the existing dma buffer if it exists */
for(int i = 0; i < sizeof(dmaInfo) / sizeof(struct DMAFrameInfo); ++i)
{
if (dmaInfo[i].frame == frame)
{
dma = &dmaInfo[i];
/* if it's too small close it */
if (dma->dataSize < dataSize)
{
close(dma->fd);
dma->fd = -1;
}
break;
}
}
/* otherwise find a free buffer for use */
if (!dma)
for(int i = 0; i < sizeof(dmaInfo) / sizeof(struct DMAFrameInfo); ++i)
{
if (!dmaInfo[i].frame)
{
dma = &dmaInfo[i];
dma->frame = frame;
dma->fd = -1;
break;
}
}
/* open the buffer */
if (dma->fd == -1)
{
const uintptr_t pos = (uintptr_t)msg.mem - (uintptr_t)state.shm.mem;
const uintptr_t offset = (uintptr_t)frame->offset + FrameBufferStructSize;
dma->dataSize = dataSize;
dma->fd = ivshmemGetDMABuf(&state.shm, pos + offset, dataSize);
if (dma->fd < 0)
{
DEBUG_ERROR("Failed to get the DMA buffer for the frame");
state.state = APP_STATE_SHUTDOWN;
break;
}
}
}
if (lgrFormat.width != state.srcSize.x || lgrFormat.height != state.srcSize.y) if (lgrFormat.width != state.srcSize.x || lgrFormat.height != state.srcSize.y)
{ {
state.srcSize.x = lgrFormat.width; state.srcSize.x = lgrFormat.width;
@ -483,7 +547,7 @@ static int frameThread(void * unused)
} }
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset); FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset);
if (!state.lgr->on_frame(state.lgrData, fb)) if (!state.lgr->on_frame(state.lgrData, fb, useDMA ? dma->fd : -1))
{ {
lgmpClientMessageDone(queue); lgmpClientMessageDone(queue);
DEBUG_ERROR("renderer on frame returned failure"); DEBUG_ERROR("renderer on frame returned failure");
@ -500,6 +564,14 @@ static int frameThread(void * unused)
lgmpClientUnsubscribe(&queue); lgmpClientUnsubscribe(&queue);
state.lgr->on_restart(state.lgrData); state.lgr->on_restart(state.lgrData);
if (useDMA)
{
for(int i = 0; i < sizeof(dmaInfo) / sizeof(struct DMAFrameInfo); ++i)
if (dmaInfo[i].fd >= 0)
close(dmaInfo[i].fd);
}
return 0; return 0;
} }