mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[host] app: allow the capture interface to select async or sync mode
While it's correct for DXGI to use a asyncronous waitFrame model, other capture interfaces such as NvFBC it is not correct. This change allows the capture interface to specify which is more correct for it and moves the waitFrame/post into the main thread if async is not desired.
This commit is contained in:
parent
eb01efe0cb
commit
e477663a7e
@ -92,6 +92,7 @@ typedef void (*CapturePostPointerBuffer)(CapturePointer pointer);
|
||||
typedef struct CaptureInterface
|
||||
{
|
||||
const char * shortName;
|
||||
const bool asyncCapture;
|
||||
const char * (*getName )();
|
||||
void (*initOptions )();
|
||||
|
||||
|
@ -236,6 +236,7 @@ static CaptureResult xcb_getFrame(FrameBuffer * frame, const unsigned int height
|
||||
struct CaptureInterface Capture_XCB =
|
||||
{
|
||||
.shortName = "XCB",
|
||||
.asyncCapture = true,
|
||||
.getName = xcb_getName,
|
||||
.create = xcb_create,
|
||||
.init = xcb_init,
|
||||
|
@ -996,6 +996,7 @@ static CaptureResult dxgi_releaseFrame(void)
|
||||
struct CaptureInterface Capture_DXGI =
|
||||
{
|
||||
.shortName = "DXGI",
|
||||
.asyncCapture = true,
|
||||
.getName = dxgi_getName,
|
||||
.initOptions = dxgi_initOptions,
|
||||
.create = dxgi_create,
|
||||
|
@ -424,6 +424,7 @@ static int pointerThread(void * unused)
|
||||
struct CaptureInterface Capture_NVFBC =
|
||||
{
|
||||
.shortName = "NvFBC",
|
||||
.asyncCapture = false,
|
||||
.getName = nvfbc_getName,
|
||||
.initOptions = nvfbc_initOptions,
|
||||
|
||||
|
@ -88,10 +88,12 @@ struct app
|
||||
unsigned int pointerIndex;
|
||||
unsigned int pointerShapeIndex;
|
||||
|
||||
long pageSize;
|
||||
size_t maxFrameSize;
|
||||
PLGMPHostQueue frameQueue;
|
||||
PLGMPMemory frameMemory[LGMP_Q_FRAME_LEN];
|
||||
unsigned int frameIndex;
|
||||
bool frameValid;
|
||||
|
||||
CaptureInterface * iface;
|
||||
|
||||
@ -140,53 +142,38 @@ static bool lgmpTimer(void * opaque)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int frameThread(void * opaque)
|
||||
static bool sendFrame(void)
|
||||
{
|
||||
DEBUG_INFO("Frame thread started");
|
||||
|
||||
bool frameValid = false;
|
||||
bool repeatFrame = false;
|
||||
CaptureFrame frame = { 0 };
|
||||
const long pageSize = sysinfo_getPageSize();
|
||||
|
||||
while(app.state == APP_STATE_RUNNING)
|
||||
{
|
||||
//wait until there is room in the queue
|
||||
if(lgmpHostQueuePending(app.frameQueue) == LGMP_Q_FRAME_LEN)
|
||||
{
|
||||
usleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool repeatFrame = false;
|
||||
switch(app.iface->waitFrame(&frame, app.maxFrameSize))
|
||||
{
|
||||
case CAPTURE_RESULT_OK:
|
||||
repeatFrame = false;
|
||||
break;
|
||||
|
||||
case CAPTURE_RESULT_REINIT:
|
||||
{
|
||||
app.state = APP_STATE_RESTART;
|
||||
DEBUG_INFO("Frame thread reinit");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
case CAPTURE_RESULT_ERROR:
|
||||
{
|
||||
DEBUG_ERROR("Failed to get the frame");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
case CAPTURE_RESULT_TIMEOUT:
|
||||
{
|
||||
if (frameValid && lgmpHostQueueNewSubs(app.frameQueue) > 0)
|
||||
if (app.frameValid && lgmpHostQueueNewSubs(app.frameQueue) > 0)
|
||||
{
|
||||
// resend the last frame
|
||||
repeatFrame = true;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +184,7 @@ static int frameThread(void * opaque)
|
||||
{
|
||||
if ((status = lgmpHostQueuePost(app.frameQueue, 0, app.frameMemory[app.frameIndex])) != LGMP_OK)
|
||||
DEBUG_ERROR("%s", lgmpStatusString(status));
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// we increment the index first so that if we need to repeat a frame
|
||||
@ -214,7 +201,7 @@ static int frameThread(void * opaque)
|
||||
case CAPTURE_FMT_RGBA16F: fi->type = FRAME_TYPE_RGBA16F; break;
|
||||
default:
|
||||
DEBUG_ERROR("Unsupported frame format %d, skipping frame", frame.format);
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(frame.rotation)
|
||||
@ -235,10 +222,10 @@ static int frameThread(void * opaque)
|
||||
fi->realHeight = frame.realHeight;
|
||||
fi->stride = frame.stride;
|
||||
fi->pitch = frame.pitch;
|
||||
fi->offset = pageSize - FrameBufferStructSize;
|
||||
fi->offset = app.pageSize - FrameBufferStructSize;
|
||||
fi->mouseScalePercent = app.iface->getMouseScale();
|
||||
fi->blockScreensaver = os_blockScreensaver();
|
||||
frameValid = true;
|
||||
app.frameValid = true;
|
||||
|
||||
// put the framebuffer on the border of the next page
|
||||
// this is to allow for aligned DMA transfers by the receiver
|
||||
@ -249,9 +236,28 @@ static int frameThread(void * opaque)
|
||||
if ((status = lgmpHostQueuePost(app.frameQueue, 0, app.frameMemory[app.frameIndex])) != LGMP_OK)
|
||||
{
|
||||
DEBUG_ERROR("%s", lgmpStatusString(status));
|
||||
return true;
|
||||
}
|
||||
|
||||
app.iface->getFrame(fb, frame.height);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int frameThread(void * opaque)
|
||||
{
|
||||
DEBUG_INFO("Frame thread started");
|
||||
|
||||
while(app.state == APP_STATE_RUNNING)
|
||||
{
|
||||
//wait until there is room in the queue
|
||||
if(lgmpHostQueuePending(app.frameQueue) == LGMP_Q_FRAME_LEN)
|
||||
{
|
||||
usleep(1);
|
||||
continue;
|
||||
}
|
||||
app.iface->getFrame(fb, frame.height);
|
||||
|
||||
if (!sendFrame())
|
||||
break;
|
||||
}
|
||||
DEBUG_INFO("Frame thread stopped");
|
||||
return 0;
|
||||
@ -260,6 +266,9 @@ static int frameThread(void * opaque)
|
||||
bool startThreads(void)
|
||||
{
|
||||
app.state = APP_STATE_RUNNING;
|
||||
if (!app.iface->asyncCapture)
|
||||
return true;
|
||||
|
||||
if (!lgCreateThread("FrameThread", frameThread, NULL, &app.frameThread))
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the frame thread");
|
||||
@ -271,20 +280,25 @@ bool startThreads(void)
|
||||
|
||||
bool stopThreads(void)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
app.iface->stop();
|
||||
if (app.state != APP_STATE_SHUTDOWN)
|
||||
app.state = APP_STATE_IDLE;
|
||||
|
||||
if (app.frameThread && !lgJoinThread(app.frameThread, NULL))
|
||||
if (!app.iface->asyncCapture)
|
||||
return true;
|
||||
|
||||
if (app.frameThread)
|
||||
{
|
||||
if (!lgJoinThread(app.frameThread, NULL))
|
||||
{
|
||||
DEBUG_WARN("Failed to join the frame thread");
|
||||
ok = false;
|
||||
app.frameThread = NULL;
|
||||
return false;
|
||||
}
|
||||
app.frameThread = NULL;
|
||||
}
|
||||
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool captureStart(void)
|
||||
@ -564,17 +578,19 @@ int app_main(int argc, char * argv[])
|
||||
memset(lgmpHostMemPtr(app.pointerShapeMemory[i]), 0, MAX_POINTER_SIZE);
|
||||
}
|
||||
|
||||
app.pageSize = sysinfo_getPageSize();
|
||||
app.frameValid = false;
|
||||
app.pointerShapeValid = false;
|
||||
|
||||
const long sz = sysinfo_getPageSize();
|
||||
app.maxFrameSize = lgmpHostMemAvail(app.lgmp);
|
||||
app.maxFrameSize = (app.maxFrameSize - (sz - 1)) & ~(sz - 1);
|
||||
app.maxFrameSize = (app.maxFrameSize - (app.pageSize - 1)) & ~(app.pageSize - 1);
|
||||
app.maxFrameSize /= LGMP_Q_FRAME_LEN;
|
||||
DEBUG_INFO("Max Frame Size : %u MiB", (unsigned int)(app.maxFrameSize / 1048576LL));
|
||||
|
||||
for(int i = 0; i < LGMP_Q_FRAME_LEN; ++i)
|
||||
{
|
||||
if ((status = lgmpHostMemAllocAligned(app.lgmp, app.maxFrameSize, sz, &app.frameMemory[i])) != LGMP_OK)
|
||||
if ((status = lgmpHostMemAllocAligned(app.lgmp, app.maxFrameSize,
|
||||
app.pageSize, &app.frameMemory[i])) != LGMP_OK)
|
||||
{
|
||||
DEBUG_ERROR("lgmpHostMemAlloc Failed (Frame): %s", lgmpStatusString(status));
|
||||
exitcode = LG_HOST_EXIT_FATAL;
|
||||
@ -616,6 +632,8 @@ int app_main(int argc, char * argv[])
|
||||
}
|
||||
|
||||
DEBUG_INFO("Using : %s", iface->getName());
|
||||
DEBUG_INFO("Capture Method : %s", iface->asyncCapture ?
|
||||
"Asynchronous" : "Synchronous");
|
||||
|
||||
app.state = APP_STATE_RUNNING;
|
||||
app.iface = iface;
|
||||
@ -710,6 +728,9 @@ int app_main(int argc, char * argv[])
|
||||
exitcode = LG_HOST_EXIT_FAILED;
|
||||
goto fail_capture;
|
||||
}
|
||||
|
||||
if (!iface->asyncCapture)
|
||||
sendFrame();
|
||||
}
|
||||
|
||||
if (app.state != APP_STATE_SHUTDOWN)
|
||||
|
Loading…
Reference in New Issue
Block a user