mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[client] copy the header and kick the guest early
This commit is contained in:
parent
e8ac71263b
commit
638f836927
@ -99,7 +99,8 @@ inline bool areFormatsSame(const struct KVMGFXHeader s1, const struct KVMGFXHead
|
||||
|
||||
int renderThread(void * unused)
|
||||
{
|
||||
struct KVMGFXHeader format;
|
||||
struct KVMGFXHeader header;
|
||||
struct KVMGFXHeader newHeader;
|
||||
SDL_Texture *texture = NULL;
|
||||
GLuint vboID[2] = {0, 0};
|
||||
GLuint intFormat = 0;
|
||||
@ -110,11 +111,7 @@ int renderThread(void * unused)
|
||||
uint8_t *pixels = (uint8_t*)state.shm;
|
||||
uint8_t *texPixels[2] = {NULL, NULL};
|
||||
|
||||
format.version = 1;
|
||||
format.frameType = FRAME_TYPE_INVALID;
|
||||
format.width = 0;
|
||||
format.height = 0;
|
||||
format.stride = 0;
|
||||
memset(&header, 0, sizeof(struct KVMGFXHeader));
|
||||
|
||||
// kick the guest early for our intial frame
|
||||
// the guestID may be invalid, it doesn't matter
|
||||
@ -122,11 +119,14 @@ int renderThread(void * unused)
|
||||
|
||||
while(state.running)
|
||||
{
|
||||
// copy the header for our use
|
||||
memcpy(&newHeader, state.shm, sizeof(struct KVMGFXHeader));
|
||||
|
||||
// ensure the header magic is valid, this will help prevent crash out when the memory hasn't yet been initialized
|
||||
if (memcmp(state.shm->magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC)) != 0)
|
||||
if (memcmp(newHeader.magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC)) != 0)
|
||||
continue;
|
||||
|
||||
if (state.shm->version != KVMGFX_HEADER_VERSION)
|
||||
if (newHeader.version != KVMGFX_HEADER_VERSION)
|
||||
continue;
|
||||
|
||||
bool ready = false;
|
||||
@ -141,7 +141,7 @@ int renderThread(void * unused)
|
||||
break;
|
||||
|
||||
case IVSHMEM_WAIT_RESULT_TIMEOUT:
|
||||
ivshmem_kick_irq(state.shm->guestID, 0);
|
||||
ivshmem_kick_irq(newHeader.guestID, 0);
|
||||
ready = false;
|
||||
break;
|
||||
|
||||
@ -157,8 +157,14 @@ int renderThread(void * unused)
|
||||
break;
|
||||
}
|
||||
|
||||
// if the format is invalid or it has changed
|
||||
if (!areFormatsSame(format, *state.shm))
|
||||
// we can tell the guest to advance early, it won't
|
||||
// touch the frame @ dataPos as it double buffers
|
||||
// so we can safely read from it while the guest now
|
||||
// writes the next frame
|
||||
ivshmem_kick_irq(newHeader.guestID, 0);
|
||||
|
||||
// if the header is invalid or it has changed
|
||||
if (!areFormatsSame(header, newHeader))
|
||||
{
|
||||
if (state.hasBufferStorage)
|
||||
{
|
||||
@ -186,7 +192,7 @@ int renderThread(void * unused)
|
||||
|
||||
Uint32 sdlFormat;
|
||||
unsigned int bpp;
|
||||
switch(state.shm->frameType)
|
||||
switch(newHeader.frameType)
|
||||
{
|
||||
case FRAME_TYPE_ARGB:
|
||||
sdlFormat = SDL_PIXELFORMAT_ARGB8888;
|
||||
@ -203,14 +209,14 @@ int renderThread(void * unused)
|
||||
break;
|
||||
|
||||
default:
|
||||
format.frameType = FRAME_TYPE_INVALID;
|
||||
header.frameType = FRAME_TYPE_INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
// update the window size and create the render texture
|
||||
if (params.autoResize)
|
||||
{
|
||||
SDL_SetWindowSize(state.window, state.shm->width, state.shm->height);
|
||||
SDL_SetWindowSize(state.window, newHeader.width, newHeader.height);
|
||||
if (params.center)
|
||||
SDL_SetWindowPosition(state.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
@ -218,10 +224,10 @@ int renderThread(void * unused)
|
||||
if (state.hasBufferStorage)
|
||||
{
|
||||
// calculate the texture size in bytes
|
||||
texSize = state.shm->width * state.shm->stride * bpp;
|
||||
texSize = newHeader.width * newHeader.stride * bpp;
|
||||
|
||||
// ensure the size makes sense
|
||||
if (state.shm->dataPos + texSize > state.shmSize)
|
||||
if (newHeader.dataPos + texSize > state.shmSize)
|
||||
{
|
||||
DEBUG_ERROR("The guest sent an invalid dataPos");
|
||||
break;
|
||||
@ -271,7 +277,7 @@ int renderThread(void * unused)
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
intFormat,
|
||||
state.shm->width, state.shm->height,
|
||||
newHeader.width, newHeader.height,
|
||||
0,
|
||||
vboFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
@ -281,7 +287,7 @@ int renderThread(void * unused)
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = SDL_CreateTexture(state.renderer, sdlFormat, SDL_TEXTUREACCESS_STREAMING, state.shm->width, state.shm->height);
|
||||
texture = SDL_CreateTexture(state.renderer, sdlFormat, SDL_TEXTUREACCESS_STREAMING, newHeader.width, newHeader.height);
|
||||
if (!texture)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create a texture");
|
||||
@ -289,19 +295,16 @@ int renderThread(void * unused)
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&format, state.shm, sizeof(format));
|
||||
memcpy(&header, &newHeader, sizeof(header));
|
||||
state.windowChanged = true;
|
||||
}
|
||||
|
||||
format.dataPos = state.shm->dataPos;
|
||||
format.guestID = state.shm->guestID;
|
||||
|
||||
//beyond this point DO NOT use state.shm for security
|
||||
|
||||
// final sanity checks on the data presented by the guest
|
||||
// this is critical as the guest could overflow this buffer to
|
||||
// try to take control of the host
|
||||
if (format.dataPos + texSize > state.shmSize)
|
||||
if (newHeader.dataPos + texSize > state.shmSize)
|
||||
{
|
||||
DEBUG_ERROR("The guest sent an invalid dataPos");
|
||||
break;
|
||||
@ -315,8 +318,7 @@ int renderThread(void * unused)
|
||||
SDL_GetWindowSize(state.window, &w, &h);
|
||||
|
||||
// copy the buffer to the texture and let the guest advance
|
||||
memcpySSE(texPixels[texIndex], pixels + format.dataPos, texSize);
|
||||
ivshmem_kick_irq(format.guestID, 0);
|
||||
memcpySSE(texPixels[texIndex], pixels + newHeader.dataPos, texSize);
|
||||
|
||||
// update the texture
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
@ -326,7 +328,7 @@ int renderThread(void * unused)
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
0, 0,
|
||||
format.width, format.height,
|
||||
header.width, header.height,
|
||||
vboFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
(void*)0
|
||||
@ -358,11 +360,10 @@ int renderThread(void * unused)
|
||||
DEBUG_ERROR("Failed to lock the texture for update");
|
||||
break;
|
||||
}
|
||||
texSize = format.height * pitch;
|
||||
texSize = header.height * pitch;
|
||||
|
||||
// copy the buffer to the texture and let the guest advance
|
||||
memcpySSE(texPixels[texIndex], pixels + format.dataPos, texSize);
|
||||
ivshmem_kick_irq(format.guestID, 0);
|
||||
memcpySSE(texPixels[texIndex], pixels + newHeader.dataPos, texSize);
|
||||
|
||||
SDL_UnlockTexture(texture);
|
||||
SDL_RenderCopy(state.renderer, texture, NULL, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user