[client] cleanup of renderer API for better usage

* Added new on_render_start for render initialization
* Changed on_resize to execute inside the render thread
This commit is contained in:
Geoffrey McRae 2018-07-28 14:49:37 +10:00
parent 13cd50f92c
commit 83592f7e4a
3 changed files with 106 additions and 110 deletions

View File

@ -35,6 +35,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
(x)->on_mouse_shape && \ (x)->on_mouse_shape && \
(x)->on_mouse_event && \ (x)->on_mouse_event && \
(x)->on_alert && \ (x)->on_alert && \
(x)->render_startup && \
(x)->render) (x)->render)
#define LGR_OPTION_COUNT(x) (sizeof(x) / sizeof(LG_RendererOpt)) #define LGR_OPTION_COUNT(x) (sizeof(x) / sizeof(LG_RendererOpt))
@ -129,6 +130,7 @@ typedef struct LG_Renderer
LG_RendererOnMouseEvent on_mouse_event; LG_RendererOnMouseEvent on_mouse_event;
LG_RendererOnFrameEvent on_frame_event; LG_RendererOnFrameEvent on_frame_event;
LG_RendererOnAlert on_alert; LG_RendererOnAlert on_alert;
LG_RendererRender render_startup;
LG_RendererRender render; LG_RendererRender render;
} }
LG_Renderer; LG_Renderer;

View File

@ -54,6 +54,7 @@ struct AppState
TTF_Font * font; TTF_Font * font;
TTF_Font * alertFont; TTF_Font * alertFont;
bool haveSrcSize; bool haveSrcSize;
int windowW, windowH;
SDL_Point srcSize; SDL_Point srcSize;
LG_RendererRect dstRect; LG_RendererRect dstRect;
SDL_Point cursor; SDL_Point cursor;
@ -64,6 +65,7 @@ struct AppState
const LG_Renderer * lgr ; const LG_Renderer * lgr ;
void * lgrData; void * lgrData;
bool lgrResize;
SDL_Window * window; SDL_Window * window;
int shmFD; int shmFD;
@ -144,36 +146,35 @@ struct AppParams params =
static inline void updatePositionInfo() static inline void updatePositionInfo()
{ {
int w, h; SDL_GetWindowSize(state.window, &state.windowW, &state.windowH);
SDL_GetWindowSize(state.window, &w, &h);
if (state.haveSrcSize) if (state.haveSrcSize)
{ {
if (params.keepAspect) if (params.keepAspect)
{ {
const float srcAspect = (float)state.srcSize.y / (float)state.srcSize.x; const float srcAspect = (float)state.srcSize.y / (float)state.srcSize.x;
const float wndAspect = (float)h / (float)w; const float wndAspect = (float)state.windowH / (float)state.windowW;
if (wndAspect < srcAspect) if (wndAspect < srcAspect)
{ {
state.dstRect.w = (float)h / srcAspect; state.dstRect.w = (float)state.windowH / srcAspect;
state.dstRect.h = h; state.dstRect.h = state.windowH;
state.dstRect.x = (w >> 1) - (state.dstRect.w >> 1); state.dstRect.x = (state.windowW >> 1) - (state.dstRect.w >> 1);
state.dstRect.y = 0; state.dstRect.y = 0;
} }
else else
{ {
state.dstRect.w = w; state.dstRect.w = state.windowW;
state.dstRect.h = (float)w * srcAspect; state.dstRect.h = (float)state.windowW * srcAspect;
state.dstRect.x = 0; state.dstRect.x = 0;
state.dstRect.y = (h >> 1) - (state.dstRect.h >> 1); state.dstRect.y = (state.windowH >> 1) - (state.dstRect.h >> 1);
} }
} }
else else
{ {
state.dstRect.x = 0; state.dstRect.x = 0;
state.dstRect.y = 0; state.dstRect.y = 0;
state.dstRect.w = w; state.dstRect.w = state.windowW;
state.dstRect.h = h; state.dstRect.h = state.windowH;
} }
state.dstRect.valid = true; state.dstRect.valid = true;
@ -181,14 +182,23 @@ static 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) state.lgrResize = true;
state.lgr->on_resize(state.lgrData, w, h, state.dstRect);
} }
int renderThread(void * unused) int renderThread(void * unused)
{ {
if (!state.lgr->render_startup(state.lgrData, state.window))
return 1;
while(state.running) while(state.running)
{ {
if (state.lgrResize)
{
if (state.lgr)
state.lgr->on_resize(state.lgrData, state.windowW, state.windowH, state.dstRect);
state.lgrResize = false;
}
const uint64_t start = microtime(); const uint64_t start = microtime();
if (!state.lgr->render(state.lgrData, state.window)) if (!state.lgr->render(state.lgrData, state.window))

View File

@ -80,13 +80,12 @@ struct Inst
struct Options opt; struct Options opt;
bool amdPinnedMemSupport; bool amdPinnedMemSupport;
bool preConfigured; bool renderStarted;
bool configured; bool configured;
bool reconfigure; bool reconfigure;
SDL_GLContext glContext; SDL_GLContext glContext;
SDL_Point window; SDL_Point window;
bool resizeWindow;
bool frameUpdate; bool frameUpdate;
LG_Lock formatLock; LG_Lock formatLock;
@ -148,7 +147,6 @@ static bool _check_gl_error(unsigned int line, const char * name);
#define check_gl_error(name) _check_gl_error(__LINE__, name) #define check_gl_error(name) _check_gl_error(__LINE__, name)
static void deconfigure(struct Inst * this); static void deconfigure(struct Inst * this);
static bool pre_configure(struct Inst * this, SDL_Window *window);
static bool configure(struct Inst * this, SDL_Window *window); static bool configure(struct Inst * this, SDL_Window *window);
static void update_mouse_shape(struct Inst * this, bool * newShape); static void update_mouse_shape(struct Inst * this, bool * newShape);
static bool draw_frame(struct Inst * this); static bool draw_frame(struct Inst * this);
@ -205,7 +203,7 @@ void opengl_deinitialize(void * opaque)
if (!this) if (!this)
return; return;
if (this->preConfigured) if (this->renderStarted)
{ {
glDeleteLists(this->texList , BUFFER_COUNT); glDeleteLists(this->texList , BUFFER_COUNT);
glDeleteLists(this->mouseList, 1); glDeleteLists(this->mouseList, 1);
@ -242,8 +240,6 @@ void opengl_deinitialize(void * opaque)
void opengl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect) void opengl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect)
{ {
struct Inst * this = (struct Inst *)opaque; struct Inst * this = (struct Inst *)opaque;
if (!this)
return;
this->window.x = width; this->window.x = width;
this->window.y = height; this->window.y = height;
@ -251,7 +247,24 @@ void opengl_on_resize(void * opaque, const int width, const int height, const LG
if (destRect.valid) if (destRect.valid)
memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect)); memcpy(&this->destRect, &destRect, sizeof(LG_RendererRect));
this->resizeWindow = true; // setup the projection matrix
glViewport(0, 0, this->window.x, this->window.y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, this->window.x, this->window.y, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (this->destRect.valid)
{
glTranslatef(this->destRect.x, this->destRect.y, 0.0f);
glScalef(
(float)this->destRect.w / (float)this->format.width,
(float)this->destRect.h / (float)this->format.height,
1.0f
);
}
} }
bool opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data) bool opengl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data)
@ -428,39 +441,71 @@ void surface_to_texture(SDL_Surface * surface, GLuint texture)
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
bool opengl_render_startup(void * opaque, SDL_Window * window)
{
struct Inst * this = (struct Inst *)opaque;
this->glContext = SDL_GL_CreateContext(window);
if (!this->glContext)
{
DEBUG_ERROR("Failed to create the OpenGL context");
return false;
}
DEBUG_INFO("Vendor : %s", glGetString(GL_VENDOR ));
DEBUG_INFO("Renderer: %s", glGetString(GL_RENDERER));
DEBUG_INFO("Version : %s", glGetString(GL_VERSION ));
GLint n;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for(GLint i = 0; i < n; ++i)
{
const GLubyte *ext = glGetStringi(GL_EXTENSIONS, i);
if (strcmp((const char *)ext, "GL_AMD_pinned_memory") == 0)
{
if (this->opt.amdPinnedMem)
{
this->amdPinnedMemSupport = true;
DEBUG_INFO("Using GL_AMD_pinned_memory");
}
else
DEBUG_INFO("GL_AMD_pinned_memory is available but not in use");
break;
}
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
glEnable(GL_MULTISAMPLE);
// generate lists for drawing
this->texList = glGenLists(BUFFER_COUNT);
this->mouseList = glGenLists(1);
this->fpsList = glGenLists(1);
this->alertList = glGenLists(1);
// create the overlay textures
glGenTextures(TEXTURE_COUNT, this->textures);
if (check_gl_error("glGenTextures"))
{
LG_UNLOCK(this->formatLock);
return false;
}
this->hasTextures = true;
SDL_GL_SetSwapInterval(this->opt.vsync ? 1 : 0);
this->renderStarted = true;
return true;
}
bool opengl_render(void * opaque, SDL_Window * window) bool opengl_render(void * opaque, SDL_Window * window)
{ {
struct Inst * this = (struct Inst *)opaque; struct Inst * this = (struct Inst *)opaque;
if (!this) if (!this)
return false; return false;
if (!pre_configure(this, window))
return false;
if (this->resizeWindow)
{
// setup the projection matrix
glViewport(0, 0, this->window.x, this->window.y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, this->window.x, this->window.y, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (this->destRect.valid)
{
glTranslatef(this->destRect.x, this->destRect.y, 0.0f);
glScalef(
(float)this->destRect.w / (float)this->format.width,
(float)this->destRect.h / (float)this->format.height,
1.0f
);
}
this->resizeWindow = false;
}
if (configure(this, window)) if (configure(this, window))
if (!draw_frame(this)) if (!draw_frame(this))
return false; return false;
@ -800,6 +845,7 @@ const LG_Renderer LGR_OpenGL =
.on_mouse_event = opengl_on_mouse_event, .on_mouse_event = opengl_on_mouse_event,
.on_frame_event = opengl_on_frame_event, .on_frame_event = opengl_on_frame_event,
.on_alert = opengl_on_alert, .on_alert = opengl_on_alert,
.render_startup = opengl_render_startup,
.render = opengl_render .render = opengl_render
}; };
@ -814,66 +860,6 @@ static bool _check_gl_error(unsigned int line, const char * name)
return true; return true;
} }
static bool pre_configure(struct Inst * this, SDL_Window *window)
{
if (this->preConfigured)
return true;
this->glContext = SDL_GL_CreateContext(window);
if (!this->glContext)
{
DEBUG_ERROR("Failed to create the OpenGL context");
return false;
}
DEBUG_INFO("Vendor : %s", glGetString(GL_VENDOR ));
DEBUG_INFO("Renderer: %s", glGetString(GL_RENDERER));
DEBUG_INFO("Version : %s", glGetString(GL_VERSION ));
GLint n;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for(GLint i = 0; i < n; ++i)
{
const GLubyte *ext = glGetStringi(GL_EXTENSIONS, i);
if (strcmp((const char *)ext, "GL_AMD_pinned_memory") == 0)
{
if (this->opt.amdPinnedMem)
{
this->amdPinnedMemSupport = true;
DEBUG_INFO("Using GL_AMD_pinned_memory");
}
else
DEBUG_INFO("GL_AMD_pinned_memory is available but not in use");
break;
}
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
glEnable(GL_MULTISAMPLE);
// generate lists for drawing
this->texList = glGenLists(BUFFER_COUNT);
this->mouseList = glGenLists(1);
this->fpsList = glGenLists(1);
this->alertList = glGenLists(1);
// create the overlay textures
glGenTextures(TEXTURE_COUNT, this->textures);
if (check_gl_error("glGenTextures"))
{
LG_UNLOCK(this->formatLock);
return false;
}
this->hasTextures = true;
SDL_GL_SetSwapInterval(this->opt.vsync ? 1 : 0);
this->preConfigured = true;
return true;
}
static bool configure(struct Inst * this, SDL_Window *window) static bool configure(struct Inst * this, SDL_Window *window)
{ {
LG_LOCK(this->formatLock); LG_LOCK(this->formatLock);
@ -1085,9 +1071,7 @@ static bool configure(struct Inst * this, SDL_Window *window)
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
this->resizeWindow = true;
this->drawStart = nanotime(); this->drawStart = nanotime();
this->configured = true; this->configured = true;
this->reconfigure = false; this->reconfigure = false;