mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 23:07:18 +00:00
[client] reworked sync code to use polling for short delays
This commit is contained in:
parent
a1f574ff2f
commit
e1a566bcad
@ -22,6 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -155,23 +156,11 @@ inline bool areFormatsSame(const struct KVMFRHeader s1, const struct KVMFRHeader
|
|||||||
(s1.height == s2.height );
|
(s1.height == s2.height );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int waitGuest()
|
inline uint64_t microtime()
|
||||||
{
|
{
|
||||||
while(state.running)
|
struct timeval time;
|
||||||
{
|
gettimeofday(&time, NULL);
|
||||||
switch(ivshmem_wait_irq(0, (1000/30)))
|
return ((uint64_t)time.tv_sec * 1000000) + time.tv_usec;
|
||||||
{
|
|
||||||
case IVSHMEM_WAIT_RESULT_OK :
|
|
||||||
case IVSHMEM_WAIT_RESULT_TIMEOUT:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case IVSHMEM_WAIT_RESULT_ERROR:
|
|
||||||
DEBUG_ERROR("error during wait for host");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int renderThread(void * unused)
|
int renderThread(void * unused)
|
||||||
@ -180,18 +169,53 @@ int renderThread(void * unused)
|
|||||||
struct KVMFRHeader header;
|
struct KVMFRHeader header;
|
||||||
const LG_Renderer * lgr = NULL;
|
const LG_Renderer * lgr = NULL;
|
||||||
void * lgrData;
|
void * lgrData;
|
||||||
unsigned int lastTicks = SDL_GetTicks();
|
|
||||||
unsigned int frameCount = 0;
|
unsigned int frameCount = 0;
|
||||||
unsigned int lastFrameCount = 0;
|
|
||||||
SDL_Texture * textTexture = NULL;
|
SDL_Texture * textTexture = NULL;
|
||||||
SDL_Rect textRect;
|
SDL_Rect textRect;
|
||||||
|
|
||||||
|
uint64_t waitTime = 0;
|
||||||
|
uint64_t presentTime = 0;
|
||||||
|
uint64_t fpsTime = 0;
|
||||||
|
|
||||||
while(state.running)
|
while(state.running)
|
||||||
{
|
{
|
||||||
if (!waitGuest())
|
glFlush();
|
||||||
|
|
||||||
|
if (waitTime < 30000 && waitTime > 2000)
|
||||||
|
usleep(waitTime - 2000);
|
||||||
|
|
||||||
|
// poll for a new frame
|
||||||
|
while(state.running && header.dataPos == state.shm->dataPos)
|
||||||
|
{
|
||||||
|
// if the frame is overdue
|
||||||
|
if (microtime() - presentTime > waitTime)
|
||||||
|
{
|
||||||
|
enum IVSHMEMWaitResult result = ivshmem_wait_irq(0, (1000/30));
|
||||||
|
if (result == IVSHMEM_WAIT_RESULT_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (result == IVSHMEM_WAIT_RESULT_TIMEOUT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (result == IVSHMEM_WAIT_RESULT_ERROR)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("error during wait for host");
|
||||||
|
state.running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.running)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++frameCount;
|
// normally you would never put this into an OpenGL application but because
|
||||||
|
// of our hybrid sleep/poll logic above the GPU has had time to finish up
|
||||||
|
// anyway. Having this here ensures that the GPU doesn't buffer up
|
||||||
|
// additional frames if the guest starts to outpace us.
|
||||||
|
glFinish();
|
||||||
|
|
||||||
|
waitTime = microtime() - presentTime;
|
||||||
|
|
||||||
// we must take a copy of the header, both to let the guest advance and to
|
// we must take a copy of the header, both to let the guest advance and to
|
||||||
// prevent the contained arguments being abused to overflow buffers
|
// prevent the contained arguments being abused to overflow buffers
|
||||||
@ -320,12 +344,13 @@ int renderThread(void * unused)
|
|||||||
if (!params.showFPS)
|
if (!params.showFPS)
|
||||||
{
|
{
|
||||||
SDL_RenderPresent(state.renderer);
|
SDL_RenderPresent(state.renderer);
|
||||||
|
presentTime = microtime();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for now render the frame counter here, we really should
|
// for now render the frame counter here, we really should
|
||||||
// move this into the renderers though.
|
// move this into the renderers though.
|
||||||
if (frameCount % 10 == 0)
|
if (fpsTime > 1000000)
|
||||||
{
|
{
|
||||||
SDL_Surface *textSurface = NULL;
|
SDL_Surface *textSurface = NULL;
|
||||||
if (textTexture)
|
if (textTexture)
|
||||||
@ -334,12 +359,11 @@ int renderThread(void * unused)
|
|||||||
textTexture = NULL;
|
textTexture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int ticks = SDL_GetTicks();
|
char str[32];
|
||||||
const float avgFPS = (float)(frameCount - lastFrameCount) / ((ticks - lastTicks) / 1000.0f);
|
const float avgFPS = 1000.0f / (((float)fpsTime / frameCount) / 1000.0f);
|
||||||
char strFPS[12];
|
snprintf(str, sizeof(str), "FPS: %8.4f", avgFPS);
|
||||||
snprintf(strFPS, sizeof(strFPS), "FPS: %6.2f", avgFPS);
|
|
||||||
SDL_Color color = {0xff, 0xff, 0xff};
|
SDL_Color color = {0xff, 0xff, 0xff};
|
||||||
if (!(textSurface = TTF_RenderText_Blended(state.font, strFPS, color)))
|
if (!(textSurface = TTF_RenderText_Blended(state.font, str, color)))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to render text");
|
DEBUG_ERROR("Failed to render text");
|
||||||
break;
|
break;
|
||||||
@ -354,8 +378,8 @@ int renderThread(void * unused)
|
|||||||
SDL_SetTextureBlendMode(textTexture, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(textTexture, SDL_BLENDMODE_BLEND);
|
||||||
SDL_FreeSurface(textSurface);
|
SDL_FreeSurface(textSurface);
|
||||||
|
|
||||||
lastTicks = ticks;
|
fpsTime = 0;
|
||||||
lastFrameCount = frameCount;
|
frameCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textTexture)
|
if (textTexture)
|
||||||
@ -386,6 +410,11 @@ int renderThread(void * unused)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_RenderPresent(state.renderer);
|
SDL_RenderPresent(state.renderer);
|
||||||
|
|
||||||
|
++frameCount;
|
||||||
|
uint64_t t = microtime();
|
||||||
|
fpsTime += t - presentTime;
|
||||||
|
presentTime = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lgr)
|
if (lgr)
|
||||||
@ -706,15 +735,7 @@ int run()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.vsync)
|
SDL_GL_SetSwapInterval(params.vsync ? 1 : 0);
|
||||||
{
|
|
||||||
// try for late swap tearing to help keep sync with the guest
|
|
||||||
if (SDL_GL_SetSwapInterval(-1) == -1)
|
|
||||||
SDL_GL_SetSwapInterval(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SDL_GL_SetSwapInterval(0);
|
|
||||||
|
|
||||||
if (params.useBufferStorage)
|
if (params.useBufferStorage)
|
||||||
{
|
{
|
||||||
const GLubyte * extensions = glGetString(GL_EXTENSIONS);
|
const GLubyte * extensions = glGetString(GL_EXTENSIONS);
|
||||||
|
Loading…
Reference in New Issue
Block a user