mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-23 14:21:57 +00:00
[client] renderer interface improvements and use gl lists for opengl
This commit is contained in:
parent
fcfea1b65d
commit
0ad1f21ffb
4 changed files with 86 additions and 73 deletions
|
@ -65,8 +65,8 @@ typedef const char * (* LG_RendererGetName )();
|
||||||
typedef bool (* LG_RendererInitialize )(void ** opaque, const LG_RendererParams params, const LG_RendererFormat format);
|
typedef bool (* LG_RendererInitialize )(void ** opaque, const LG_RendererParams params, const LG_RendererFormat format);
|
||||||
typedef void (* LG_RendererDeInitialize)(void * opaque);
|
typedef void (* LG_RendererDeInitialize)(void * opaque);
|
||||||
typedef bool (* LG_RendererIsCompatible)(void * opaque, const LG_RendererFormat format);
|
typedef bool (* LG_RendererIsCompatible)(void * opaque, const LG_RendererFormat format);
|
||||||
typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height);
|
typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect);
|
||||||
typedef bool (* LG_RendererRender )(void * opaque, const LG_RendererRect destRect, const uint8_t * data, bool resample);
|
typedef bool (* LG_RendererRender )(void * opaque, const uint8_t * data, bool resample);
|
||||||
|
|
||||||
typedef struct LG_Renderer
|
typedef struct LG_Renderer
|
||||||
{
|
{
|
||||||
|
|
|
@ -136,7 +136,7 @@ inline void updatePositionInfo()
|
||||||
state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w;
|
state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w;
|
||||||
|
|
||||||
if (state.lgr)
|
if (state.lgr)
|
||||||
state.lgr->on_resize(state.lgrData, w, h);
|
state.lgr->on_resize(state.lgrData, w, h, state.dstRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
int renderThread(void * unused)
|
int renderThread(void * unused)
|
||||||
|
@ -303,7 +303,6 @@ int renderThread(void * unused)
|
||||||
|
|
||||||
if (!state.lgr->render(
|
if (!state.lgr->render(
|
||||||
state.lgrData,
|
state.lgrData,
|
||||||
state.dstRect,
|
|
||||||
(uint8_t *)state.shm + header.dataPos,
|
(uint8_t *)state.shm + header.dataPos,
|
||||||
params.useMipmap
|
params.useMipmap
|
||||||
))
|
))
|
||||||
|
@ -612,11 +611,6 @@ int run()
|
||||||
FcPatternDestroy(pat);
|
FcPatternDestroy(pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// while this is related to opengl, it must happen before the window is created
|
|
||||||
// as such it can not be part of the opengl renderer
|
|
||||||
if (!params.vsync)
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
|
|
||||||
|
|
||||||
state.window = SDL_CreateWindow(
|
state.window = SDL_CreateWindow(
|
||||||
"Looking Glass (Client)",
|
"Looking Glass (Client)",
|
||||||
params.center ? SDL_WINDOWPOS_CENTERED : params.x,
|
params.center ? SDL_WINDOWPOS_CENTERED : params.x,
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct LGR_Basic
|
||||||
size_t dataWidth;
|
size_t dataWidth;
|
||||||
SDL_Renderer * renderer;
|
SDL_Renderer * renderer;
|
||||||
SDL_Texture * texture;
|
SDL_Texture * texture;
|
||||||
|
SDL_Rect destRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * lgr_basic_get_name()
|
const char * lgr_basic_get_name()
|
||||||
|
@ -110,14 +111,19 @@ bool lgr_basic_is_compatible(void * opaque, const LG_RendererFormat format)
|
||||||
return (memcmp(&this->format, &format, sizeof(LG_RendererFormat)) == 0);
|
return (memcmp(&this->format, &format, sizeof(LG_RendererFormat)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lgr_basic_on_resize(void * opaque, const int width, const int height)
|
void lgr_basic_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect)
|
||||||
{
|
{
|
||||||
const struct LGR_Basic * this = (struct LGR_Basic *)opaque;
|
struct LGR_Basic * this = (struct LGR_Basic *)opaque;
|
||||||
if (!this || !this->initialized)
|
if (!this || !this->initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
this->destRect.x = destRect.x;
|
||||||
|
this->destRect.y = destRect.y;
|
||||||
|
this->destRect.w = destRect.w;
|
||||||
|
this->destRect.h = destRect.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lgr_basic_render(void * opaque, const LG_RendererRect destRect, const uint8_t * data, bool resample)
|
bool lgr_basic_render(void * opaque, const uint8_t * data, bool resample)
|
||||||
{
|
{
|
||||||
struct LGR_Basic * this = (struct LGR_Basic *)opaque;
|
struct LGR_Basic * this = (struct LGR_Basic *)opaque;
|
||||||
if (!this || !this->initialized)
|
if (!this || !this->initialized)
|
||||||
|
@ -144,14 +150,8 @@ bool lgr_basic_render(void * opaque, const LG_RendererRect destRect, const uint8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Rect rect;
|
|
||||||
rect.x = destRect.x;
|
|
||||||
rect.y = destRect.y;
|
|
||||||
rect.w = destRect.w;
|
|
||||||
rect.h = destRect.h;
|
|
||||||
|
|
||||||
SDL_UnlockTexture(this->texture);
|
SDL_UnlockTexture(this->texture);
|
||||||
SDL_RenderCopy(this->renderer, this->texture, NULL, &rect);
|
SDL_RenderCopy(this->renderer, this->texture, NULL, &this->destRect);
|
||||||
SDL_RenderPresent(this->renderer);
|
SDL_RenderPresent(this->renderer);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -37,6 +37,9 @@ struct LGR_OpenGL
|
||||||
GLuint vboID[VBO_BUFFERS];
|
GLuint vboID[VBO_BUFFERS];
|
||||||
uint8_t * texPixels[VBO_BUFFERS];
|
uint8_t * texPixels[VBO_BUFFERS];
|
||||||
int texIndex;
|
int texIndex;
|
||||||
|
int texList;
|
||||||
|
int fpsList;
|
||||||
|
LG_RendererRect destRect;
|
||||||
|
|
||||||
bool hasTextures;
|
bool hasTextures;
|
||||||
GLuint vboTex[VBO_BUFFERS + 1]; // extra texture for FPS
|
GLuint vboTex[VBO_BUFFERS + 1]; // extra texture for FPS
|
||||||
|
@ -49,7 +52,7 @@ struct LGR_OpenGL
|
||||||
SDL_Rect fpsRect;
|
SDL_Rect fpsRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
void lgr_opengl_on_resize(void * opaque, const int width, const int height);
|
void lgr_opengl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect);
|
||||||
|
|
||||||
bool lgr_opengl_check_error(const char * name)
|
bool lgr_opengl_check_error(const char * name)
|
||||||
{
|
{
|
||||||
|
@ -139,6 +142,10 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
|
||||||
// calculate the texture size in bytes
|
// calculate the texture size in bytes
|
||||||
this->texSize = format.height * format.pitch;
|
this->texSize = format.height * format.pitch;
|
||||||
|
|
||||||
|
// generate lists for drawing
|
||||||
|
this->texList = glGenLists(2);
|
||||||
|
this->fpsList = glGenLists(1);
|
||||||
|
|
||||||
// generate the pixel unpack buffers
|
// generate the pixel unpack buffers
|
||||||
glGenBuffers(VBO_BUFFERS, this->vboID);
|
glGenBuffers(VBO_BUFFERS, this->vboID);
|
||||||
if (lgr_opengl_check_error("glGenBuffers"))
|
if (lgr_opengl_check_error("glGenBuffers"))
|
||||||
|
@ -239,7 +246,7 @@ bool lgr_opengl_is_compatible(void * opaque, const LG_RendererFormat format)
|
||||||
return (memcmp(&this->format, &format, sizeof(LG_RendererFormat)) == 0);
|
return (memcmp(&this->format, &format, sizeof(LG_RendererFormat)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lgr_opengl_on_resize(void * opaque, const int width, const int height)
|
void lgr_opengl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect)
|
||||||
{
|
{
|
||||||
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
|
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
|
||||||
if (!this || !this->initialized)
|
if (!this || !this->initialized)
|
||||||
|
@ -247,10 +254,12 @@ void lgr_opengl_on_resize(void * opaque, const int width, const int height)
|
||||||
|
|
||||||
this->params.width = width;
|
this->params.width = width;
|
||||||
this->params.height = height;
|
this->params.height = height;
|
||||||
|
memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect));
|
||||||
|
|
||||||
this->resizeWindow = true;
|
this->resizeWindow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint8_t * data, bool resample)
|
bool lgr_opengl_render(void * opaque, const uint8_t * data, bool resample)
|
||||||
{
|
{
|
||||||
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
|
struct LGR_OpenGL * this = (struct LGR_OpenGL *)opaque;
|
||||||
if (!this || !this->initialized)
|
if (!this || !this->initialized)
|
||||||
|
@ -270,11 +279,26 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluOrtho2D(0, this->params.width, this->params.height, 0);
|
gluOrtho2D(0, this->params.width, this->params.height, 0);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
this->resizeWindow = false;
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
DEBUG_INFO("resize");
|
||||||
|
for(int i = 0; i < VBO_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
glNewList(this->texList + i, GL_COMPILE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->vboTex[i]);
|
||||||
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
glTexCoord2f(0.0f, 0.0f); glVertex2i(this->destRect.x , this->destRect.y );
|
||||||
|
glTexCoord2f(1.0f, 0.0f); glVertex2i(this->destRect.x + this->destRect.w, this->destRect.y );
|
||||||
|
glTexCoord2f(0.0f, 1.0f); glVertex2i(this->destRect.x , this->destRect.y + this->destRect.h);
|
||||||
|
glTexCoord2f(1.0f, 1.0f); glVertex2i(this->destRect.x + this->destRect.w, this->destRect.y + this->destRect.h);
|
||||||
|
glEnd();
|
||||||
|
glEndList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->resizeWindow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
if (this->params.showFPS && this->renderTime > 1e9)
|
if (this->params.showFPS && this->renderTime > 1e9)
|
||||||
{
|
{
|
||||||
char str[128];
|
char str[128];
|
||||||
|
@ -320,78 +344,8 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint
|
||||||
this->renderTime = 0;
|
this->renderTime = 0;
|
||||||
this->frameCount = 0;
|
this->frameCount = 0;
|
||||||
this->fpsTexture = true;
|
this->fpsTexture = true;
|
||||||
}
|
|
||||||
|
|
||||||
// copy the buffer to the texture
|
glNewList(this->fpsList, GL_COMPILE);
|
||||||
memcpySSE(this->texPixels[this->texIndex], data, this->texSize);
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[this->texIndex]);
|
|
||||||
glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, this->texSize);
|
|
||||||
|
|
||||||
// bind the texture and update it
|
|
||||||
glBindTexture(GL_TEXTURE_2D , this->vboTex[this->texIndex]);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH , this->format.width );
|
|
||||||
|
|
||||||
// wait until the last frame has been presented
|
|
||||||
glFlush();
|
|
||||||
uint count;
|
|
||||||
glXGetVideoSyncSGI(&count);
|
|
||||||
if (this->gpuFrameCount == count)
|
|
||||||
{
|
|
||||||
uint remainder;
|
|
||||||
glXWaitVideoSyncSGI(count, 1, &remainder);
|
|
||||||
this->gpuFrameCount = count + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this->gpuFrameCount = count;
|
|
||||||
|
|
||||||
// update the texture
|
|
||||||
glTexSubImage2D(
|
|
||||||
GL_TEXTURE_2D,
|
|
||||||
0,
|
|
||||||
0, 0,
|
|
||||||
this->format.width ,
|
|
||||||
this->format.height,
|
|
||||||
this->vboFormat,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
(void*)0
|
|
||||||
);
|
|
||||||
|
|
||||||
const bool mipmap = resample && (
|
|
||||||
(this->format.width > destRect.w) ||
|
|
||||||
(this->format.height > destRect.h));
|
|
||||||
|
|
||||||
// unbind the buffer
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
|
|
||||||
// configure the texture
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
if (mipmap)
|
|
||||||
{
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw the screen
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->vboTex[this->texIndex]);
|
|
||||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
|
||||||
glTexCoord2f(0.0f, 0.0f); glVertex2i(destRect.x , destRect.y );
|
|
||||||
glTexCoord2f(1.0f, 0.0f); glVertex2i(destRect.x + destRect.w, destRect.y );
|
|
||||||
glTexCoord2f(0.0f, 1.0f); glVertex2i(destRect.x , destRect.y + destRect.h);
|
|
||||||
glTexCoord2f(1.0f, 1.0f); glVertex2i(destRect.x + destRect.w, destRect.y + destRect.h);
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
if (this->fpsTexture)
|
|
||||||
{
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
glColor4f(0.0f, 0.0f, 1.0f, 0.5f);
|
glColor4f(0.0f, 0.0f, 1.0f, 0.5f);
|
||||||
|
@ -412,11 +366,76 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint
|
||||||
glTexCoord2f(1.0f, 1.0f); glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y + this->fpsRect.h);
|
glTexCoord2f(1.0f, 1.0f); glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y + this->fpsRect.h);
|
||||||
glEnd();
|
glEnd();
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
glEndList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy the buffer to the texture
|
||||||
|
memcpySSE(this->texPixels[this->texIndex], data, this->texSize);
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[this->texIndex]);
|
||||||
|
glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, this->texSize);
|
||||||
|
|
||||||
|
// bind the texture and update it
|
||||||
|
glBindTexture(GL_TEXTURE_2D , this->vboTex[this->texIndex]);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH , this->format.width );
|
||||||
|
|
||||||
|
// update the texture
|
||||||
|
glTexSubImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
0, 0,
|
||||||
|
this->format.width ,
|
||||||
|
this->format.height,
|
||||||
|
this->vboFormat,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
(void*)0
|
||||||
|
);
|
||||||
|
|
||||||
|
const bool mipmap = resample && (
|
||||||
|
(this->format.width > this->destRect.w) ||
|
||||||
|
(this->format.height > this->destRect.h));
|
||||||
|
|
||||||
|
// unbind the buffer
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
|
// configure the texture
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
if (mipmap)
|
||||||
|
{
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the screen
|
||||||
|
glCallList(this->texList + this->texIndex);
|
||||||
|
|
||||||
|
if (this->fpsTexture)
|
||||||
|
glCallList(this->fpsList);
|
||||||
|
|
||||||
++this->frameCount;
|
++this->frameCount;
|
||||||
if (this->params.vsync)
|
|
||||||
SDL_GL_SwapWindow(this->params.window);
|
SDL_GL_SwapWindow(this->params.window);
|
||||||
|
glFlush();
|
||||||
|
|
||||||
|
// wait until the frame has been presented, this is to avoid the video card
|
||||||
|
// buffering frames, we would rather skip a frame then fall behind the guest
|
||||||
|
uint count;
|
||||||
|
glXGetVideoSyncSGI(&count);
|
||||||
|
if (this->gpuFrameCount == count)
|
||||||
|
{
|
||||||
|
uint remainder;
|
||||||
|
glXWaitVideoSyncSGI(count, 1, &remainder);
|
||||||
|
this->gpuFrameCount = count + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->gpuFrameCount = count;
|
||||||
|
|
||||||
const uint64_t t = nanotime();
|
const uint64_t t = nanotime();
|
||||||
this->renderTime += t - this->lastFrameTime;
|
this->renderTime += t - this->lastFrameTime;
|
||||||
|
|
Loading…
Reference in a new issue