mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[client] opengl: optimize software surface uploads
This commit is contained in:
@@ -140,6 +140,8 @@ struct Inst
|
|||||||
int swSurfaceList;
|
int swSurfaceList;
|
||||||
LG_RendererRect destRect;
|
LG_RendererRect destRect;
|
||||||
struct IntPoint swSurfaceSize;
|
struct IntPoint swSurfaceSize;
|
||||||
|
uint8_t * swSurfaceBuffer;
|
||||||
|
size_t swSurfaceBufferSize;
|
||||||
bool showSwSurface;
|
bool showSwSurface;
|
||||||
|
|
||||||
bool hasTextures, hasFrames;
|
bool hasTextures, hasFrames;
|
||||||
@@ -181,6 +183,24 @@ static bool drawFrame(struct Inst * this,
|
|||||||
LG_RendererFrameToken * consumedFrameToken);
|
LG_RendererFrameToken * consumedFrameToken);
|
||||||
static void drawMouse(struct Inst * this);
|
static void drawMouse(struct Inst * this);
|
||||||
|
|
||||||
|
static bool swSurfaceEnsureBuffer(struct Inst * this, size_t size)
|
||||||
|
{
|
||||||
|
if (size <= this->swSurfaceBufferSize)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
uint8_t * buffer = realloc(this->swSurfaceBuffer, size);
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to allocate %zu bytes for software surface upload",
|
||||||
|
size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->swSurfaceBuffer = buffer;
|
||||||
|
this->swSurfaceBufferSize = size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const char * opengl_getName(void)
|
const char * opengl_getName(void)
|
||||||
{
|
{
|
||||||
return "OpenGL";
|
return "OpenGL";
|
||||||
@@ -250,6 +270,8 @@ void opengl_deinitialize(LG_Renderer * renderer)
|
|||||||
if (this->mouseData)
|
if (this->mouseData)
|
||||||
free(this->mouseData);
|
free(this->mouseData);
|
||||||
|
|
||||||
|
free(this->swSurfaceBuffer);
|
||||||
|
|
||||||
if (this->glContext)
|
if (this->glContext)
|
||||||
{
|
{
|
||||||
app_glDeleteContext(this->glContext);
|
app_glDeleteContext(this->glContext);
|
||||||
@@ -655,37 +677,31 @@ static void opengl_swSurfaceDrawFill(LG_Renderer * renderer,
|
|||||||
height = (bottom > this->swSurfaceSize.y ?
|
height = (bottom > this->swSurfaceSize.y ?
|
||||||
this->swSurfaceSize.y : (int)bottom) - y;
|
this->swSurfaceSize.y : (int)bottom) - y;
|
||||||
|
|
||||||
/* This is a fairly hacky way to update a software surface, but it preserves
|
const size_t pixels = (size_t)width * (size_t)height;
|
||||||
* the existing incremental fill behavior. */
|
const size_t size = pixels * sizeof(uint32_t);
|
||||||
|
if (!swSurfaceEnsureBuffer(this, size))
|
||||||
uint32_t * line = malloc((size_t)width * sizeof(*line));
|
|
||||||
if (!line)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to allocate software surface fill row");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < width; ++i)
|
uint32_t * pixelsData = (uint32_t *)this->swSurfaceBuffer;
|
||||||
line[i] = color;
|
for(size_t i = 0; i < pixels; ++i)
|
||||||
|
pixelsData[i] = color;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
for(int dy = 0; dy < height; ++dy)
|
|
||||||
glTexSubImage2D
|
glTexSubImage2D
|
||||||
(
|
(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
0 ,
|
0 ,
|
||||||
x ,
|
x ,
|
||||||
y + dy ,
|
y ,
|
||||||
width ,
|
width ,
|
||||||
1 ,
|
height ,
|
||||||
GL_BGRA,
|
GL_BGRA,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
line
|
pixelsData
|
||||||
);
|
);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
free(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void opengl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
static void opengl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
||||||
@@ -698,27 +714,6 @@ static void opengl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
|||||||
stride <= 0 || width > stride / 4)
|
stride <= 0 || width > stride / 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!topDown)
|
|
||||||
{
|
|
||||||
// This is non-optimal, but the incremental surface is a fallback.
|
|
||||||
uint8_t * line = malloc((size_t)stride);
|
|
||||||
if (!line)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to allocate software surface bitmap row");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int y = 0; y < height / 2; ++y)
|
|
||||||
{
|
|
||||||
uint8_t * top = data + y * stride;
|
|
||||||
uint8_t * btm = data + (height - y - 1) * stride;
|
|
||||||
memcpy(line, top , stride);
|
|
||||||
memcpy(top , btm , stride);
|
|
||||||
memcpy(btm , line, stride);
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int64_t right = (int64_t)x + width;
|
const int64_t right = (int64_t)x + width;
|
||||||
const int64_t bottom = (int64_t)y + height;
|
const int64_t bottom = (int64_t)y + height;
|
||||||
if (x >= this->swSurfaceSize.x ||
|
if (x >= this->swSurfaceSize.x ||
|
||||||
@@ -728,17 +723,41 @@ static void opengl_swSurfaceDrawBitmap(LG_Renderer * renderer,
|
|||||||
|
|
||||||
const int sourceX = x < 0 ? -x : 0;
|
const int sourceX = x < 0 ? -x : 0;
|
||||||
const int sourceY = y < 0 ? -y : 0;
|
const int sourceY = y < 0 ? -y : 0;
|
||||||
|
const int sourceHeight = height;
|
||||||
x = x < 0 ? 0 : x;
|
x = x < 0 ? 0 : x;
|
||||||
y = y < 0 ? 0 : y;
|
y = y < 0 ? 0 : y;
|
||||||
width = (right > this->swSurfaceSize.x ?
|
width = (right > this->swSurfaceSize.x ?
|
||||||
this->swSurfaceSize.x : (int)right ) - x;
|
this->swSurfaceSize.x : (int)right ) - x;
|
||||||
height = (bottom > this->swSurfaceSize.y ?
|
height = (bottom > this->swSurfaceSize.y ?
|
||||||
this->swSurfaceSize.y : (int)bottom) - y;
|
this->swSurfaceSize.y : (int)bottom) - y;
|
||||||
|
int uploadStride;
|
||||||
|
if (topDown)
|
||||||
|
{
|
||||||
data += (size_t)sourceY * stride + (size_t)sourceX * 4;
|
data += (size_t)sourceY * stride + (size_t)sourceX * 4;
|
||||||
|
uploadStride = stride;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const size_t rowSize = (size_t)width * 4;
|
||||||
|
const size_t size = rowSize * (size_t)height;
|
||||||
|
if (!swSurfaceEnsureBuffer(this, size))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(int dy = 0; dy < height; ++dy)
|
||||||
|
{
|
||||||
|
const int sourceRow = sourceHeight - sourceY - dy - 1;
|
||||||
|
memcpy(this->swSurfaceBuffer + (size_t)dy * rowSize,
|
||||||
|
data + (size_t)sourceRow * stride + (size_t)sourceX * 4,
|
||||||
|
rowSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = this->swSurfaceBuffer;
|
||||||
|
uploadStride = width * 4;
|
||||||
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[SW_SURFACE_TEXTURE]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / 4);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, uploadStride / 4);
|
||||||
glTexSubImage2D
|
glTexSubImage2D
|
||||||
(
|
(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
|
|||||||
Reference in New Issue
Block a user