mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-14 01:58:25 +00:00
[client] another try at better screen sync
This commit is contained in:
parent
81f4a7fade
commit
a7180a5609
@ -14,11 +14,12 @@
|
|||||||
#include "memcpySSE.h"
|
#include "memcpySSE.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define VBO_BUFFERS 2
|
#define BUFFER_COUNT 2
|
||||||
|
|
||||||
#define FPS_TEXTURE (VBO_BUFFERS )
|
#define FRAME_TEXTURE 0
|
||||||
#define MOUSE_TEXTURE (VBO_BUFFERS+1)
|
#define FPS_TEXTURE 1
|
||||||
#define TEXTURE_COUNT (VBO_BUFFERS+2)
|
#define MOUSE_TEXTURE 2
|
||||||
|
#define TEXTURE_COUNT 3
|
||||||
|
|
||||||
static PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI = NULL;
|
static PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI = NULL;
|
||||||
static PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI = NULL;
|
static PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI = NULL;
|
||||||
@ -38,13 +39,14 @@ struct LGR_OpenGL
|
|||||||
|
|
||||||
uint64_t drawStart;
|
uint64_t drawStart;
|
||||||
bool hasBuffers;
|
bool hasBuffers;
|
||||||
GLuint vboID[VBO_BUFFERS];
|
GLuint vboID[1];
|
||||||
uint8_t * texPixels[VBO_BUFFERS];
|
uint8_t * texPixels[BUFFER_COUNT];
|
||||||
int texIndex;
|
int texIndex;
|
||||||
int texList;
|
int texList;
|
||||||
int fpsList;
|
int fpsList;
|
||||||
int mouseList;
|
int mouseList;
|
||||||
LG_RendererRect destRect;
|
LG_RendererRect destRect;
|
||||||
|
bool mipmap;
|
||||||
|
|
||||||
bool hasTextures;
|
bool hasTextures;
|
||||||
GLuint textures[TEXTURE_COUNT];
|
GLuint textures[TEXTURE_COUNT];
|
||||||
@ -59,8 +61,6 @@ struct LGR_OpenGL
|
|||||||
bool mouseUpdate;
|
bool mouseUpdate;
|
||||||
uint64_t lastMouseDraw;
|
uint64_t lastMouseDraw;
|
||||||
LG_RendererCursor mouseType;
|
LG_RendererCursor mouseType;
|
||||||
bool mouseRepair;
|
|
||||||
SDL_Rect mouseRepairPos;
|
|
||||||
bool mouseVisible;
|
bool mouseVisible;
|
||||||
SDL_Rect mousePos;
|
SDL_Rect mousePos;
|
||||||
};
|
};
|
||||||
@ -124,7 +124,7 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SetSwapInterval(0);
|
SDL_GL_SetSwapInterval(1);
|
||||||
|
|
||||||
// check if the GPU supports GL_ARB_buffer_storage first
|
// check if the GPU supports GL_ARB_buffer_storage first
|
||||||
// there is no advantage to this renderer if it is not present.
|
// there is no advantage to this renderer if it is not present.
|
||||||
@ -157,40 +157,45 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
|
|||||||
this->texSize = format.height * format.pitch;
|
this->texSize = format.height * format.pitch;
|
||||||
|
|
||||||
// generate lists for drawing
|
// generate lists for drawing
|
||||||
this->texList = glGenLists(2);
|
this->texList = glGenLists(BUFFER_COUNT);
|
||||||
this->fpsList = glGenLists(1);
|
this->fpsList = glGenLists(1);
|
||||||
this->mouseList = glGenLists(1);
|
this->mouseList = glGenLists(1);
|
||||||
|
|
||||||
// generate the pixel unpack buffers
|
// generate the pixel unpack buffers
|
||||||
glGenBuffers(VBO_BUFFERS, this->vboID);
|
glGenBuffers(1, this->vboID);
|
||||||
if (lgr_opengl_check_error("glGenBuffers"))
|
if (lgr_opengl_check_error("glGenBuffers"))
|
||||||
return false;
|
return false;
|
||||||
this->hasBuffers = true;
|
this->hasBuffers = true;
|
||||||
|
|
||||||
// persistant bind the buffers
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[0]);
|
||||||
for (int i = 0; i < VBO_BUFFERS; ++i)
|
if (lgr_opengl_check_error("glBindBuffer"))
|
||||||
{
|
return false;
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[i]);
|
|
||||||
if (lgr_opengl_check_error("glBindBuffer"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, this->texSize, 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
|
glBufferStorage(
|
||||||
if (lgr_opengl_check_error("glBufferStorage"))
|
GL_PIXEL_UNPACK_BUFFER,
|
||||||
return false;
|
this->texSize * BUFFER_COUNT,
|
||||||
|
NULL,
|
||||||
|
GL_MAP_WRITE_BIT |
|
||||||
|
GL_MAP_PERSISTENT_BIT |
|
||||||
|
GL_MAP_COHERENT_BIT
|
||||||
|
);
|
||||||
|
if (lgr_opengl_check_error("glBufferStorage"))
|
||||||
|
return false;
|
||||||
|
|
||||||
this->texPixels[i] = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, this->texSize,
|
this->texPixels[0] = glMapBufferRange(
|
||||||
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
|
GL_PIXEL_UNPACK_BUFFER,
|
||||||
if (lgr_opengl_check_error("glMapBufferRange"))
|
0,
|
||||||
return false;
|
this->texSize * BUFFER_COUNT,
|
||||||
|
GL_MAP_WRITE_BIT |
|
||||||
|
GL_MAP_PERSISTENT_BIT |
|
||||||
|
GL_MAP_COHERENT_BIT
|
||||||
|
);
|
||||||
|
|
||||||
if (!this->texPixels[i])
|
if (lgr_opengl_check_error("glMapBufferRange"))
|
||||||
{
|
return false;
|
||||||
DEBUG_ERROR("Failed to map the buffer range");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
for(int i = 1; i < BUFFER_COUNT; ++i)
|
||||||
}
|
this->texPixels[i] = this->texPixels[i-1] + this->texSize;
|
||||||
|
|
||||||
// create the textures
|
// create the textures
|
||||||
glGenTextures(TEXTURE_COUNT, this->textures);
|
glGenTextures(TEXTURE_COUNT, this->textures);
|
||||||
@ -198,43 +203,51 @@ bool lgr_opengl_initialize(void ** opaque, const LG_RendererParams params, const
|
|||||||
return false;
|
return false;
|
||||||
this->hasTextures = true;
|
this->hasTextures = true;
|
||||||
|
|
||||||
// bind the textures to the unpack buffers
|
// create the frame texture
|
||||||
for (int i = 0; i < VBO_BUFFERS; ++i)
|
glBindTexture(GL_TEXTURE_2D, this->textures[FRAME_TEXTURE]);
|
||||||
{
|
if (lgr_opengl_check_error("glBindTexture"))
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[i]);
|
return false;
|
||||||
if (lgr_opengl_check_error("glBindTexture"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
glTexImage2D(
|
glTexImage2D(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
this->intFormat,
|
this->intFormat,
|
||||||
format.width, format.height,
|
format.width,
|
||||||
0,
|
format.height * BUFFER_COUNT,
|
||||||
this->vboFormat,
|
0,
|
||||||
GL_UNSIGNED_BYTE,
|
this->vboFormat,
|
||||||
(void*)0
|
GL_UNSIGNED_BYTE,
|
||||||
);
|
(void*)0
|
||||||
if (lgr_opengl_check_error("glTexImage2D"))
|
);
|
||||||
return false;
|
if (lgr_opengl_check_error("glTexImage2D"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
for (int i = 0; i < BUFFER_COUNT; ++i)
|
||||||
|
{
|
||||||
|
const float ts = (1.0f / BUFFER_COUNT) * i;
|
||||||
|
const float te = (1.0f / BUFFER_COUNT) + ts;
|
||||||
|
|
||||||
// create the display lists
|
// create the display lists
|
||||||
glNewList(this->texList + i, GL_COMPILE);
|
glNewList(this->texList + i, GL_COMPILE);
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[i]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[FRAME_TEXTURE]);
|
||||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
glTexCoord2f(0.0f, 0.0f); glVertex2i(0 , 0 );
|
glTexCoord2f(0.0f, ts); glVertex2i(0 , 0 );
|
||||||
glTexCoord2f(1.0f, 0.0f); glVertex2i(format.width, 0 );
|
glTexCoord2f(1.0f, ts); glVertex2i(format.width, 0 );
|
||||||
glTexCoord2f(0.0f, 1.0f); glVertex2i(0 , format.height);
|
glTexCoord2f(0.0f, te); glVertex2i(0 , format.height);
|
||||||
glTexCoord2f(1.0f, 1.0f); glVertex2i(format.width, format.height);
|
glTexCoord2f(1.0f, te); glVertex2i(format.width, format.height);
|
||||||
glEnd();
|
glEnd();
|
||||||
glEndList();
|
glEndList();
|
||||||
|
|
||||||
if (lgr_opengl_check_error("glTexImage2D"))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glEnable(GL_COLOR_MATERIAL);
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
@ -259,10 +272,10 @@ void lgr_opengl_deinitialize(void * opaque)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (this->hasTextures)
|
if (this->hasTextures)
|
||||||
glDeleteTextures(VBO_BUFFERS, this->textures);
|
glDeleteTextures(TEXTURE_COUNT, this->textures);
|
||||||
|
|
||||||
if (this->hasBuffers)
|
if (this->hasBuffers)
|
||||||
glDeleteBuffers(VBO_BUFFERS, this->vboID);
|
glDeleteBuffers(1, this->vboID);
|
||||||
|
|
||||||
if (this->glContext)
|
if (this->glContext)
|
||||||
SDL_GL_DeleteContext(this->glContext);
|
SDL_GL_DeleteContext(this->glContext);
|
||||||
@ -440,7 +453,7 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data, bool resampl
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
int texIndex = this->texIndex + 1;
|
int texIndex = this->texIndex + 1;
|
||||||
if (texIndex == VBO_BUFFERS)
|
if (texIndex == BUFFER_COUNT)
|
||||||
texIndex = 0;
|
texIndex = 0;
|
||||||
|
|
||||||
if (this->params.showFPS && this->renderTime > 1e9)
|
if (this->params.showFPS && this->renderTime > 1e9)
|
||||||
@ -456,7 +469,7 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data, bool resampl
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D , this->textures[VBO_BUFFERS]);
|
glBindTexture(GL_TEXTURE_2D , this->textures[FPS_TEXTURE]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, textSurface->w );
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, textSurface->w );
|
||||||
glTexImage2D(
|
glTexImage2D(
|
||||||
@ -501,7 +514,7 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data, bool resampl
|
|||||||
glEnd();
|
glEnd();
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->textures[VBO_BUFFERS]);
|
glBindTexture(GL_TEXTURE_2D, this->textures[FPS_TEXTURE]);
|
||||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
glTexCoord2f(0.0f , 0.0f); glVertex2i(this->fpsRect.x , this->fpsRect.y );
|
glTexCoord2f(0.0f , 0.0f); glVertex2i(this->fpsRect.x , this->fpsRect.y );
|
||||||
@ -515,47 +528,45 @@ bool lgr_opengl_on_frame_event(void * opaque, const uint8_t * data, bool resampl
|
|||||||
|
|
||||||
// copy the buffer to the texture
|
// copy the buffer to the texture
|
||||||
memcpySSE(this->texPixels[texIndex], data, this->texSize);
|
memcpySSE(this->texPixels[texIndex], data, this->texSize);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[texIndex]);
|
|
||||||
glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, this->texSize);
|
|
||||||
|
|
||||||
// bind the texture and update it
|
// bind the texture and update it
|
||||||
glBindTexture(GL_TEXTURE_2D , this->textures[texIndex]);
|
glBindTexture(GL_TEXTURE_2D , this->textures[FRAME_TEXTURE]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[0] );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH , this->format.width );
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH , this->format.width );
|
||||||
|
|
||||||
// update the texture
|
// update the texture
|
||||||
glTexSubImage2D(
|
glTexSubImage2D(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
0, 0,
|
0,
|
||||||
|
texIndex * this->format.height,
|
||||||
this->format.width ,
|
this->format.width ,
|
||||||
this->format.height,
|
this->format.height,
|
||||||
this->vboFormat,
|
this->vboFormat,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
(void*)0
|
(void*)(texIndex * this->texSize)
|
||||||
);
|
);
|
||||||
|
lgr_opengl_check_error("glTexSubImage2D");
|
||||||
|
|
||||||
|
// unbind the buffer
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
const bool mipmap = resample && (
|
const bool mipmap = resample && (
|
||||||
(this->format.width > this->destRect.w) ||
|
(this->format.width > this->destRect.w) ||
|
||||||
(this->format.height > this->destRect.h));
|
(this->format.height > this->destRect.h));
|
||||||
|
|
||||||
// unbind the buffer
|
if (this->mipmap != mipmap)
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||||
|
mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
|
||||||
|
this->mipmap = mipmap;
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
if (mipmap)
|
||||||
{
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
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);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->frameUpdate = true;
|
this->frameUpdate = true;
|
||||||
this->texIndex = texIndex;
|
this->texIndex = texIndex;
|
||||||
@ -567,11 +578,8 @@ inline void lgr_opengl_draw_mouse(struct LGR_OpenGL * this)
|
|||||||
if (!this->mouseVisible)
|
if (!this->mouseVisible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(&this->mouseRepairPos, &this->mousePos, sizeof(SDL_Rect));
|
|
||||||
this->mouseRepair = true;
|
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(this->mouseRepairPos.x, this->mouseRepairPos.y, 0.0f);
|
glTranslatef(this->mousePos.x, this->mousePos.y, 0.0f);
|
||||||
glCallList(this->mouseList);
|
glCallList(this->mouseList);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
@ -613,6 +621,7 @@ bool lgr_opengl_render(void * opaque)
|
|||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!this->frameUpdate)
|
if (!this->frameUpdate)
|
||||||
{
|
{
|
||||||
if (!this->mouseUpdate)
|
if (!this->mouseUpdate)
|
||||||
@ -623,29 +632,22 @@ bool lgr_opengl_render(void * opaque)
|
|||||||
if (delta < 1e7)
|
if (delta < 1e7)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
glDrawBuffer(GL_FRONT);
|
||||||
glCallList(this->texList + this->texIndex);
|
glCallList(this->texList + this->texIndex);
|
||||||
lgr_opengl_draw_mouse(this);
|
lgr_opengl_draw_mouse(this);
|
||||||
glFinish();
|
glFlush();
|
||||||
|
|
||||||
this->mouseUpdate = false;
|
this->mouseUpdate = false;
|
||||||
this->lastMouseDraw = nanotime();
|
this->lastMouseDraw = nanotime();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
glDrawBuffer(GL_BACK);
|
|
||||||
glCallList(this->texList + this->texIndex);
|
|
||||||
lgr_opengl_draw_mouse(this);
|
|
||||||
if (this->fpsTexture)
|
|
||||||
glCallList(this->fpsList);
|
|
||||||
glDrawBuffer(GL_FRONT);
|
|
||||||
|
|
||||||
unsigned int count;
|
glDrawBuffer(GL_BACK);
|
||||||
glXGetVideoSyncSGI(&count);
|
glCallList(this->texList + this->texIndex);
|
||||||
if (count == this->gpuFrameCount)
|
lgr_opengl_draw_mouse(this);
|
||||||
glXWaitVideoSyncSGI(1, 0, &count);
|
if (this->fpsTexture)
|
||||||
SDL_GL_SwapWindow(this->params.window);
|
glCallList(this->fpsList);
|
||||||
glXGetVideoSyncSGI(&this->gpuFrameCount);
|
SDL_GL_SwapWindow(this->params.window);
|
||||||
}
|
|
||||||
|
|
||||||
++this->frameCount;
|
++this->frameCount;
|
||||||
const uint64_t t = nanotime();
|
const uint64_t t = nanotime();
|
||||||
|
Loading…
Reference in New Issue
Block a user