mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 13:37:22 +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)
|
int renderThread(void * unused)
|
||||||
{
|
{
|
||||||
struct KVMGFXHeader format;
|
struct KVMGFXHeader header;
|
||||||
|
struct KVMGFXHeader newHeader;
|
||||||
SDL_Texture *texture = NULL;
|
SDL_Texture *texture = NULL;
|
||||||
GLuint vboID[2] = {0, 0};
|
GLuint vboID[2] = {0, 0};
|
||||||
GLuint intFormat = 0;
|
GLuint intFormat = 0;
|
||||||
@ -110,11 +111,7 @@ int renderThread(void * unused)
|
|||||||
uint8_t *pixels = (uint8_t*)state.shm;
|
uint8_t *pixels = (uint8_t*)state.shm;
|
||||||
uint8_t *texPixels[2] = {NULL, NULL};
|
uint8_t *texPixels[2] = {NULL, NULL};
|
||||||
|
|
||||||
format.version = 1;
|
memset(&header, 0, sizeof(struct KVMGFXHeader));
|
||||||
format.frameType = FRAME_TYPE_INVALID;
|
|
||||||
format.width = 0;
|
|
||||||
format.height = 0;
|
|
||||||
format.stride = 0;
|
|
||||||
|
|
||||||
// kick the guest early for our intial frame
|
// kick the guest early for our intial frame
|
||||||
// the guestID may be invalid, it doesn't matter
|
// the guestID may be invalid, it doesn't matter
|
||||||
@ -122,11 +119,14 @@ int renderThread(void * unused)
|
|||||||
|
|
||||||
while(state.running)
|
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
|
// 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;
|
continue;
|
||||||
|
|
||||||
if (state.shm->version != KVMGFX_HEADER_VERSION)
|
if (newHeader.version != KVMGFX_HEADER_VERSION)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool ready = false;
|
bool ready = false;
|
||||||
@ -141,7 +141,7 @@ int renderThread(void * unused)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IVSHMEM_WAIT_RESULT_TIMEOUT:
|
case IVSHMEM_WAIT_RESULT_TIMEOUT:
|
||||||
ivshmem_kick_irq(state.shm->guestID, 0);
|
ivshmem_kick_irq(newHeader.guestID, 0);
|
||||||
ready = false;
|
ready = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -157,8 +157,14 @@ int renderThread(void * unused)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the format is invalid or it has changed
|
// we can tell the guest to advance early, it won't
|
||||||
if (!areFormatsSame(format, *state.shm))
|
// 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)
|
if (state.hasBufferStorage)
|
||||||
{
|
{
|
||||||
@ -186,7 +192,7 @@ int renderThread(void * unused)
|
|||||||
|
|
||||||
Uint32 sdlFormat;
|
Uint32 sdlFormat;
|
||||||
unsigned int bpp;
|
unsigned int bpp;
|
||||||
switch(state.shm->frameType)
|
switch(newHeader.frameType)
|
||||||
{
|
{
|
||||||
case FRAME_TYPE_ARGB:
|
case FRAME_TYPE_ARGB:
|
||||||
sdlFormat = SDL_PIXELFORMAT_ARGB8888;
|
sdlFormat = SDL_PIXELFORMAT_ARGB8888;
|
||||||
@ -203,14 +209,14 @@ int renderThread(void * unused)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
format.frameType = FRAME_TYPE_INVALID;
|
header.frameType = FRAME_TYPE_INVALID;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the window size and create the render texture
|
// update the window size and create the render texture
|
||||||
if (params.autoResize)
|
if (params.autoResize)
|
||||||
{
|
{
|
||||||
SDL_SetWindowSize(state.window, state.shm->width, state.shm->height);
|
SDL_SetWindowSize(state.window, newHeader.width, newHeader.height);
|
||||||
if (params.center)
|
if (params.center)
|
||||||
SDL_SetWindowPosition(state.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
SDL_SetWindowPosition(state.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||||
}
|
}
|
||||||
@ -218,10 +224,10 @@ int renderThread(void * unused)
|
|||||||
if (state.hasBufferStorage)
|
if (state.hasBufferStorage)
|
||||||
{
|
{
|
||||||
// calculate the texture size in bytes
|
// 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
|
// 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");
|
DEBUG_ERROR("The guest sent an invalid dataPos");
|
||||||
break;
|
break;
|
||||||
@ -271,7 +277,7 @@ int renderThread(void * unused)
|
|||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
intFormat,
|
intFormat,
|
||||||
state.shm->width, state.shm->height,
|
newHeader.width, newHeader.height,
|
||||||
0,
|
0,
|
||||||
vboFormat,
|
vboFormat,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
@ -281,7 +287,7 @@ int renderThread(void * unused)
|
|||||||
}
|
}
|
||||||
else
|
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)
|
if (!texture)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create a 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;
|
state.windowChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
format.dataPos = state.shm->dataPos;
|
|
||||||
format.guestID = state.shm->guestID;
|
|
||||||
|
|
||||||
//beyond this point DO NOT use state.shm for security
|
//beyond this point DO NOT use state.shm for security
|
||||||
|
|
||||||
// final sanity checks on the data presented by the guest
|
// final sanity checks on the data presented by the guest
|
||||||
// this is critical as the guest could overflow this buffer to
|
// this is critical as the guest could overflow this buffer to
|
||||||
// try to take control of the host
|
// 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");
|
DEBUG_ERROR("The guest sent an invalid dataPos");
|
||||||
break;
|
break;
|
||||||
@ -315,8 +318,7 @@ int renderThread(void * unused)
|
|||||||
SDL_GetWindowSize(state.window, &w, &h);
|
SDL_GetWindowSize(state.window, &w, &h);
|
||||||
|
|
||||||
// copy the buffer to the texture and let the guest advance
|
// copy the buffer to the texture and let the guest advance
|
||||||
memcpySSE(texPixels[texIndex], pixels + format.dataPos, texSize);
|
memcpySSE(texPixels[texIndex], pixels + newHeader.dataPos, texSize);
|
||||||
ivshmem_kick_irq(format.guestID, 0);
|
|
||||||
|
|
||||||
// update the texture
|
// update the texture
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
@ -326,7 +328,7 @@ int renderThread(void * unused)
|
|||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
0, 0,
|
0, 0,
|
||||||
format.width, format.height,
|
header.width, header.height,
|
||||||
vboFormat,
|
vboFormat,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
(void*)0
|
(void*)0
|
||||||
@ -358,11 +360,10 @@ int renderThread(void * unused)
|
|||||||
DEBUG_ERROR("Failed to lock the texture for update");
|
DEBUG_ERROR("Failed to lock the texture for update");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
texSize = format.height * pitch;
|
texSize = header.height * pitch;
|
||||||
|
|
||||||
// copy the buffer to the texture and let the guest advance
|
// copy the buffer to the texture and let the guest advance
|
||||||
memcpySSE(texPixels[texIndex], pixels + format.dataPos, texSize);
|
memcpySSE(texPixels[texIndex], pixels + newHeader.dataPos, texSize);
|
||||||
ivshmem_kick_irq(format.guestID, 0);
|
|
||||||
|
|
||||||
SDL_UnlockTexture(texture);
|
SDL_UnlockTexture(texture);
|
||||||
SDL_RenderCopy(state.renderer, texture, NULL, NULL);
|
SDL_RenderCopy(state.renderer, texture, NULL, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user