mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-25 00:12:44 +00:00
[client] opengl: validate framebuffer uploads
This commit is contained in:
@@ -131,6 +131,7 @@ struct Inst
|
|||||||
GLuint dataFormat;
|
GLuint dataFormat;
|
||||||
size_t texSize;
|
size_t texSize;
|
||||||
size_t texPos;
|
size_t texPos;
|
||||||
|
bool texUploadError;
|
||||||
float scaleX, scaleY;
|
float scaleX, scaleY;
|
||||||
const FrameBuffer * frame;
|
const FrameBuffer * frame;
|
||||||
LG_RendererFrameToken pendingFrameToken;
|
LG_RendererFrameToken pendingFrameToken;
|
||||||
@@ -1313,6 +1314,14 @@ static bool opengl_bufferFn(void * opaque, const void * data, size_t size)
|
|||||||
{
|
{
|
||||||
struct Inst * this = (struct Inst *)opaque;
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
|
||||||
|
if (this->texPos > this->texSize || size > this->texSize - this->texPos)
|
||||||
|
{
|
||||||
|
this->texUploadError = true;
|
||||||
|
DEBUG_ERROR("Texture upload exceeds its buffer (%zu + %zu > %zu)",
|
||||||
|
this->texPos, size, this->texSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// update the buffer, this performs a DMA transfer if possible
|
// update the buffer, this performs a DMA transfer if possible
|
||||||
g_gl_dynProcs.glBufferSubData(
|
g_gl_dynProcs.glBufferSubData(
|
||||||
GL_PIXEL_UNPACK_BUFFER,
|
GL_PIXEL_UNPACK_BUFFER,
|
||||||
@@ -1322,7 +1331,10 @@ static bool opengl_bufferFn(void * opaque, const void * data, size_t size)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (check_gl_error("glBufferSubData"))
|
if (check_gl_error("glBufferSubData"))
|
||||||
|
{
|
||||||
|
this->texUploadError = true;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this->texPos += size;
|
this->texPos += size;
|
||||||
return true;
|
return true;
|
||||||
@@ -1385,7 +1397,11 @@ static bool drawFrame(struct Inst * this,
|
|||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.frameWidth);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.frameWidth);
|
||||||
|
|
||||||
this->texPos = 0;
|
this->texPos = 0;
|
||||||
framebuffer_read_fn(
|
this->texUploadError = false;
|
||||||
|
const size_t expectedSize =
|
||||||
|
(size_t)this->format.dataHeight *
|
||||||
|
(size_t)this->format.dataWidth * (size_t)bpp;
|
||||||
|
const bool readComplete = framebuffer_read_fn(
|
||||||
frame,
|
frame,
|
||||||
this->format.dataHeight,
|
this->format.dataHeight,
|
||||||
this->format.dataWidth,
|
this->format.dataWidth,
|
||||||
@@ -1395,8 +1411,31 @@ static bool drawFrame(struct Inst * this,
|
|||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const bool incomplete = !readComplete || this->texPos != expectedSize;
|
||||||
|
const bool fatal = this->texUploadError ||
|
||||||
|
(readComplete && this->texPos != expectedSize);
|
||||||
|
if (incomplete && !fatal)
|
||||||
|
{
|
||||||
|
this->frame = frame;
|
||||||
|
this->pendingFrameToken = pendingFrameToken;
|
||||||
|
this->frameRelease = release;
|
||||||
|
atomic_store_explicit(&this->frameUpdate, true, memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
LG_UNLOCK(this->frameLock);
|
LG_UNLOCK(this->frameLock);
|
||||||
|
|
||||||
|
if (incomplete)
|
||||||
|
{
|
||||||
|
g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
LG_UNLOCK(this->formatLock);
|
||||||
|
if (fatal)
|
||||||
|
invokeFrameRelease(release);
|
||||||
|
DEBUG_WARN("%s incomplete texture upload (%zu of %zu bytes)",
|
||||||
|
fatal ? "Rejecting" : "Retrying", this->texPos, expectedSize);
|
||||||
|
return !fatal;
|
||||||
|
}
|
||||||
|
|
||||||
// update the texture
|
// update the texture
|
||||||
glTexSubImage2D(
|
glTexSubImage2D(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
@@ -1423,6 +1462,11 @@ static bool drawFrame(struct Inst * this,
|
|||||||
this->vboFormat,
|
this->vboFormat,
|
||||||
this->texSize
|
this->texSize
|
||||||
);
|
);
|
||||||
|
g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
LG_UNLOCK(this->formatLock);
|
||||||
|
invokeFrameRelease(release);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unbind the buffer
|
// unbind the buffer
|
||||||
|
|||||||
Reference in New Issue
Block a user