From 0ad1f21ffbd0da8a5eb0104a8d25815c68bb1022 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Mon, 11 Dec 2017 03:47:07 +1100 Subject: [PATCH] [client] renderer interface improvements and use gl lists for opengl --- client/lg-renderer.h | 4 +- client/main.c | 8 +-- client/renderers/basic.c | 20 +++--- client/renderers/opengl.c | 127 ++++++++++++++++++++++---------------- 4 files changed, 86 insertions(+), 73 deletions(-) diff --git a/client/lg-renderer.h b/client/lg-renderer.h index a3b2dc9d..545b28bf 100644 --- a/client/lg-renderer.h +++ b/client/lg-renderer.h @@ -65,8 +65,8 @@ typedef const char * (* LG_RendererGetName )(); typedef bool (* LG_RendererInitialize )(void ** opaque, const LG_RendererParams params, const LG_RendererFormat format); typedef void (* LG_RendererDeInitialize)(void * opaque); typedef bool (* LG_RendererIsCompatible)(void * opaque, const LG_RendererFormat format); -typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height); -typedef bool (* LG_RendererRender )(void * opaque, const LG_RendererRect destRect, const uint8_t * data, bool resample); +typedef void (* LG_RendererOnResize )(void * opaque, const int width, const int height, const LG_RendererRect destRect); +typedef bool (* LG_RendererRender )(void * opaque, const uint8_t * data, bool resample); typedef struct LG_Renderer { diff --git a/client/main.c b/client/main.c index 63bf455d..a2abfcd2 100644 --- a/client/main.c +++ b/client/main.c @@ -136,7 +136,7 @@ inline void updatePositionInfo() state.scaleY = (float)state.srcSize.x / (float)state.dstRect.w; 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) @@ -303,7 +303,6 @@ int renderThread(void * unused) if (!state.lgr->render( state.lgrData, - state.dstRect, (uint8_t *)state.shm + header.dataPos, params.useMipmap )) @@ -612,11 +611,6 @@ int run() 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( "Looking Glass (Client)", params.center ? SDL_WINDOWPOS_CENTERED : params.x, diff --git a/client/renderers/basic.c b/client/renderers/basic.c index 3f89b087..9714118c 100644 --- a/client/renderers/basic.c +++ b/client/renderers/basic.c @@ -15,6 +15,7 @@ struct LGR_Basic size_t dataWidth; SDL_Renderer * renderer; SDL_Texture * texture; + SDL_Rect destRect; }; 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); } -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) 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; 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_RenderCopy(this->renderer, this->texture, NULL, &rect); + SDL_RenderCopy(this->renderer, this->texture, NULL, &this->destRect); SDL_RenderPresent(this->renderer); return true; diff --git a/client/renderers/opengl.c b/client/renderers/opengl.c index 6cc93c80..c3089b62 100644 --- a/client/renderers/opengl.c +++ b/client/renderers/opengl.c @@ -37,6 +37,9 @@ struct LGR_OpenGL GLuint vboID[VBO_BUFFERS]; uint8_t * texPixels[VBO_BUFFERS]; int texIndex; + int texList; + int fpsList; + LG_RendererRect destRect; bool hasTextures; GLuint vboTex[VBO_BUFFERS + 1]; // extra texture for FPS @@ -49,7 +52,7 @@ struct LGR_OpenGL 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) { @@ -139,6 +142,10 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const // calculate the texture size in bytes this->texSize = format.height * format.pitch; + // generate lists for drawing + this->texList = glGenLists(2); + this->fpsList = glGenLists(1); + // generate the pixel unpack buffers glGenBuffers(VBO_BUFFERS, this->vboID); 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); } -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; 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.height = height; + memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect)); + 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; if (!this || !this->initialized) @@ -270,11 +279,26 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint glLoadIdentity(); gluOrtho2D(0, this->params.width, this->params.height, 0); 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) { char str[128]; @@ -289,8 +313,8 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint } glBindTexture(GL_TEXTURE_2D , this->vboTex[VBO_BUFFERS]); - glPixelStorei(GL_UNPACK_ALIGNMENT , 4 ); - glPixelStorei(GL_UNPACK_ROW_LENGTH, textSurface->w ); + glPixelStorei(GL_UNPACK_ALIGNMENT , 4 ); + glPixelStorei(GL_UNPACK_ROW_LENGTH, textSurface->w ); glTexImage2D( GL_TEXTURE_2D, 0, @@ -320,6 +344,29 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint this->renderTime = 0; this->frameCount = 0; this->fpsTexture = true; + + glNewList(this->fpsList, GL_COMPILE); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glColor4f(0.0f, 0.0f, 1.0f, 0.5f); + glBegin(GL_TRIANGLE_STRIP); + glVertex2i(this->fpsRect.x , this->fpsRect.y ); + glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y ); + glVertex2i(this->fpsRect.x , this->fpsRect.y + this->fpsRect.h); + glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y + this->fpsRect.h); + glEnd(); + glEnable(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, this->vboTex[VBO_BUFFERS]); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f(0.0f , 0.0f); glVertex2i(this->fpsRect.x , this->fpsRect.y ); + glTexCoord2f(1.0f , 0.0f); glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y ); + glTexCoord2f(0.0f , 1.0f); glVertex2i(this->fpsRect.x , 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(); + glDisable(GL_BLEND); + glEndList(); } // copy the buffer to the texture @@ -333,19 +380,6 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint 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, @@ -359,8 +393,8 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint ); const bool mipmap = resample && ( - (this->format.width > destRect.w) || - (this->format.height > destRect.h)); + (this->format.width > this->destRect.w) || + (this->format.height > this->destRect.h)); // unbind the buffer glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); @@ -381,42 +415,27 @@ bool lgr_opengl_render(void * opaque, const LG_RendererRect destRect, const uint } // 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(); + glCallList(this->texList + this->texIndex); if (this->fpsTexture) - { - glEnable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glColor4f(0.0f, 0.0f, 1.0f, 0.5f); - glBegin(GL_TRIANGLE_STRIP); - glVertex2i(this->fpsRect.x , this->fpsRect.y ); - glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y ); - glVertex2i(this->fpsRect.x , this->fpsRect.y + this->fpsRect.h); - glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y + this->fpsRect.h); - glEnd(); - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, this->vboTex[VBO_BUFFERS]); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2f(0.0f , 0.0f); glVertex2i(this->fpsRect.x , this->fpsRect.y ); - glTexCoord2f(1.0f , 0.0f); glVertex2i(this->fpsRect.x + this->fpsRect.w, this->fpsRect.y ); - glTexCoord2f(0.0f , 1.0f); glVertex2i(this->fpsRect.x , 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(); - glDisable(GL_BLEND); - } + glCallList(this->fpsList); ++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(); this->renderTime += t - this->lastFrameTime;